Coverage Report

Created: 2026-04-01 07:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavcodec/fmvc.c
Line
Count
Source
1
/*
2
 * FM 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
32
389k
#define BLOCK_HEIGHT 112u
33
477k
#define BLOCK_WIDTH  84u
34
35
typedef struct InterBlock {
36
    int      w, h;
37
    int      size;
38
    int      xor;
39
} InterBlock;
40
41
typedef struct FMVCContext {
42
    GetByteContext  gb;
43
    PutByteContext  pb;
44
    uint8_t        *buffer;
45
    size_t          buffer_size;
46
    uint8_t        *pbuffer;
47
    size_t          pbuffer_size;
48
    ptrdiff_t       stride;
49
    int             bpp;
50
    int             yb, xb;
51
    InterBlock     *blocks;
52
    unsigned        nb_blocks;
53
} FMVCContext;
54
55
static int decode_type2(GetByteContext *gb, PutByteContext *pb)
56
13.8k
{
57
13.8k
    unsigned repeat = 0, first = 1, opcode = 0;
58
13.8k
    int i, len, pos;
59
60
548k
    while (bytestream2_get_bytes_left(gb) > 0) {
61
535k
        GetByteContext gbc;
62
63
1.97M
        while (bytestream2_get_bytes_left(gb) > 0) {
64
1.96M
            if (first) {
65
13.3k
                first = 0;
66
13.3k
                if (bytestream2_peek_byte(gb) > 17) {
67
3.13k
                    len = bytestream2_get_byte(gb) - 17;
68
3.13k
                    if (len < 4) {
69
2.78k
                        do {
70
2.78k
                            bytestream2_put_byte(pb, bytestream2_get_byte(gb));
71
2.78k
                            --len;
72
2.78k
                        } while (len);
73
1.01k
                        opcode = bytestream2_peek_byte(gb);
74
1.01k
                        continue;
75
2.12k
                    } else {
76
109k
                        do {
77
109k
                            bytestream2_put_byte(pb, bytestream2_get_byte(gb));
78
109k
                            --len;
79
109k
                        } while (len);
80
2.12k
                        opcode = bytestream2_peek_byte(gb);
81
2.12k
                        if (opcode < 0x10) {
82
1.61k
                            bytestream2_skip(gb, 1);
83
1.61k
                            pos = - (opcode >> 2) - 4 * bytestream2_get_byte(gb) - 2049;
84
85
1.61k
                            bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
86
1.61k
                            bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
87
88
1.61k
                            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
89
1.61k
                            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
90
1.61k
                            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
91
1.61k
                            len = opcode & 3;
92
1.61k
                            if (!len) {
93
602
                                repeat = 1;
94
1.00k
                            } else {
95
2.77k
                                do {
96
2.77k
                                    bytestream2_put_byte(pb, bytestream2_get_byte(gb));
97
2.77k
                                    --len;
98
2.77k
                                } while (len);
99
1.00k
                                opcode = bytestream2_peek_byte(gb);
100
1.00k
                            }
101
1.61k
                            continue;
102
1.61k
                        }
103
2.12k
                    }
104
3.13k
                }
105
10.7k
                repeat = 1;
106
10.7k
            }
107
1.96M
            if (repeat) {
108
577k
                repeat = 0;
109
577k
                opcode = bytestream2_peek_byte(gb);
110
577k
                if (opcode < 0x10) {
111
328k
                    bytestream2_skip(gb, 1);
112
328k
                    if (!opcode) {
113
46.1k
                        if (!bytestream2_peek_byte(gb)) {
114
1.44M
                            do {
115
1.44M
                                bytestream2_skip(gb, 1);
116
1.44M
                                opcode += 255;
117
1.44M
                            } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);
118
14.7k
                        }
119
46.1k
                        opcode += bytestream2_get_byte(gb) + 15;
120
46.1k
                    }
121
328k
                    bytestream2_put_le32(pb, bytestream2_get_le32(gb));
122
373M
                    for (i = opcode - 1; i > 0; --i)
123
372M
                        bytestream2_put_byte(pb, bytestream2_get_byte(gb));
124
328k
                    opcode = bytestream2_peek_byte(gb);
125
328k
                    if (opcode < 0x10) {
126
294k
                        bytestream2_skip(gb, 1);
127
294k
                        pos = - (opcode >> 2) - 4 * bytestream2_get_byte(gb) - 2049;
128
129
294k
                        bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
130
294k
                        bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
131
132
294k
                        bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
133
294k
                        bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
134
294k
                        bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
135
294k
                        len = opcode & 3;
136
294k
                        if (!len) {
137
231k
                            repeat = 1;
138
231k
                        } else {
139
126k
                            do {
140
126k
                                bytestream2_put_byte(pb, bytestream2_get_byte(gb));
141
126k
                                --len;
142
126k
                            } while (len);
143
62.4k
                            opcode = bytestream2_peek_byte(gb);
144
62.4k
                        }
145
294k
                        continue;
146
294k
                    }
147
328k
                }
148
577k
            }
149
150
1.67M
            if (opcode >= 0x40) {
151
962k
                bytestream2_skip(gb, 1);
152
962k
                pos = - ((opcode >> 2) & 7) - 1 - 8 * bytestream2_get_byte(gb);
153
962k
                len =    (opcode >> 5)      - 1;
154
155
962k
                bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
156
962k
                bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
157
158
962k
                bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
159
962k
                bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
160
4.55M
                do {
161
4.55M
                    bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
162
4.55M
                    --len;
163
4.55M
                } while (len);
164
165
962k
                len = opcode & 3;
166
167
962k
                if (!len) {
168
159k
                    repeat = 1;
169
802k
                } else {
170
1.73M
                    do {
171
1.73M
                        bytestream2_put_byte(pb, bytestream2_get_byte(gb));
172
1.73M
                        --len;
173
1.73M
                    } while (len);
174
802k
                    opcode = bytestream2_peek_byte(gb);
175
802k
                }
176
962k
                continue;
177
962k
            } else if (opcode < 0x20) {
178
524k
                break;
179
524k
            }
180
184k
            len = opcode & 0x1F;
181
184k
            bytestream2_skip(gb, 1);
182
184k
            if (!len) {
183
50.3k
                if (!bytestream2_peek_byte(gb)) {
184
227k
                    do {
185
227k
                        bytestream2_skip(gb, 1);
186
227k
                        len += 255;
187
227k
                    } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);
188
40.7k
                }
189
50.3k
                len += bytestream2_get_byte(gb) + 31;
190
50.3k
            }
191
184k
            i = bytestream2_get_le16(gb);
192
184k
            pos = - (i >> 2) - 1;
193
194
184k
            bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
195
184k
            bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
196
197
184k
            if (len < 6 || bytestream2_tell_p(pb) - bytestream2_tell(&gbc) < 4) {
198
18.4k
                bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
199
18.4k
                bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
200
6.80M
                do {
201
6.80M
                    bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
202
6.80M
                    --len;
203
6.80M
                } while (len);
204
165k
            } else {
205
165k
                bytestream2_put_le32(pb, bytestream2_get_le32(&gbc));
206
55.5M
                for (len = len - 2; len; --len)
207
55.4M
                    bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
208
165k
            }
209
184k
            len = i & 3;
210
184k
            if (!len) {
211
37.1k
                repeat = 1;
212
147k
            } else {
213
347k
                do {
214
347k
                    bytestream2_put_byte(pb, bytestream2_get_byte(gb));
215
347k
                    --len;
216
347k
                } while (len);
217
147k
                opcode = bytestream2_peek_byte(gb);
218
147k
            }
219
184k
        }
220
535k
        bytestream2_skip(gb, 1);
221
535k
        if (opcode < 0x10) {
222
396k
            pos = -(opcode >> 2) - 1 - 4 * bytestream2_get_byte(gb);
223
224
396k
            bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
225
396k
            bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
226
227
396k
            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
228
396k
            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
229
396k
            len = opcode & 3;
230
396k
            if (!len) {
231
142k
                repeat = 1;
232
253k
            } else {
233
473k
                do {
234
473k
                    bytestream2_put_byte(pb, bytestream2_get_byte(gb));
235
473k
                    --len;
236
473k
                } while (len);
237
253k
                opcode = bytestream2_peek_byte(gb);
238
253k
            }
239
396k
            continue;
240
396k
        }
241
139k
        len = opcode & 7;
242
139k
        if (!len) {
243
13.6k
            if (!bytestream2_peek_byte(gb)) {
244
196k
                do {
245
196k
                    bytestream2_skip(gb, 1);
246
196k
                    len += 255;
247
196k
                } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);
248
9.67k
            }
249
13.6k
            len += bytestream2_get_byte(gb) + 7;
250
13.6k
        }
251
139k
        i = bytestream2_get_le16(gb);
252
139k
        pos = bytestream2_tell_p(pb) - 2048 * (opcode & 8);
253
139k
        pos = pos - (i >> 2);
254
139k
        if (pos == bytestream2_tell_p(pb))
255
1.40k
            break;
256
257
138k
        pos = pos - 0x4000;
258
138k
        bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
259
138k
        bytestream2_seek(&gbc, pos, SEEK_SET);
260
261
138k
        if (len < 6 || bytestream2_tell_p(pb) - bytestream2_tell(&gbc) < 4) {
262
107k
            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
263
107k
            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
264
48.0M
            do {
265
48.0M
                bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
266
48.0M
                --len;
267
48.0M
            } while (len);
268
107k
        } else {
269
30.4k
            bytestream2_put_le32(pb, bytestream2_get_le32(&gbc));
270
3.73M
            for (len = len - 2; len; --len)
271
3.70M
                bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
272
30.4k
        }
273
274
138k
        len = i & 3;
275
138k
        if (!len) {
276
13.4k
            repeat = 1;
277
124k
        } else {
278
171k
            do {
279
171k
                bytestream2_put_byte(pb, bytestream2_get_byte(gb));
280
171k
                --len;
281
171k
            } while (len);
282
124k
            opcode = bytestream2_peek_byte(gb);
283
124k
        }
284
138k
    }
285
286
13.8k
    return 0;
287
13.8k
}
288
289
static int decode_type1(GetByteContext *gb, PutByteContext *pb)
290
139k
{
291
139k
    unsigned opcode = 0, len;
292
139k
    int high = 0;
293
139k
    int i, pos;
294
295
180k
    while (bytestream2_get_bytes_left(gb) > 0) {
296
179k
        GetByteContext gbc;
297
298
675k
        while (bytestream2_get_bytes_left(gb) > 0) {
299
545k
            while (bytestream2_get_bytes_left(gb) > 0) {
300
543k
                opcode = bytestream2_get_byte(gb);
301
543k
                high = opcode >= 0x20;
302
543k
                if (high)
303
512k
                    break;
304
30.4k
                if (opcode)
305
14.5k
                    break;
306
15.8k
                opcode = bytestream2_get_byte(gb);
307
15.8k
                if (opcode < 0xF8) {
308
13.2k
                    opcode += 32;
309
13.2k
                    break;
310
13.2k
                }
311
2.63k
                i = opcode - 0xF8;
312
2.63k
                if (i) {
313
2.19k
                    len = 256;
314
13.6k
                    do {
315
13.6k
                        len *= 2;
316
13.6k
                        --i;
317
13.6k
                    } while (i);
318
2.19k
                } else {
319
443
                    len = 280;
320
443
                }
321
962k
                do {
322
962k
                    bytestream2_put_le32(pb, bytestream2_get_le32(gb));
323
962k
                    bytestream2_put_le32(pb, bytestream2_get_le32(gb));
324
962k
                    len -= 8;
325
962k
                } while (len && bytestream2_get_bytes_left(gb) > 0);
326
2.63k
            }
327
328
542k
            if (!high) {
329
452k
                do {
330
452k
                    bytestream2_put_byte(pb, bytestream2_get_byte(gb));
331
452k
                    --opcode;
332
452k
                } while (opcode && bytestream2_get_bytes_left(gb) > 0);
333
334
384k
                while (bytestream2_get_bytes_left(gb) > 0) {
335
376k
                    GetByteContext gbc;
336
337
376k
                    opcode = bytestream2_get_byte(gb);
338
376k
                    if (opcode >= 0x20)
339
22.5k
                        break;
340
354k
                    bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
341
342
354k
                    pos = -(opcode | 32 * bytestream2_get_byte(gb)) - 1;
343
354k
                    bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
344
354k
                    bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
345
354k
                    bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
346
354k
                    bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
347
354k
                    bytestream2_put_byte(pb, bytestream2_get_byte(gb));
348
354k
                }
349
29.9k
            }
350
542k
            high = 0;
351
542k
            if (opcode < 0x40)
352
46.5k
                break;
353
496k
            bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
354
496k
            pos = (-((opcode & 0x1F) | 32 * bytestream2_get_byte(gb)) - 1);
355
496k
            bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
356
496k
            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
357
496k
            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
358
496k
            len = (opcode >> 5) - 1;
359
2.64M
            do {
360
2.64M
                bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
361
2.64M
                --len;
362
2.64M
            } while (len && bytestream2_get_bytes_left(&gbc) > 0);
363
496k
        }
364
179k
        len = opcode & 0x1F;
365
179k
        if (!len) {
366
9.12k
            if (!bytestream2_peek_byte(gb)) {
367
1.58M
                do {
368
1.58M
                    bytestream2_skip(gb, 1);
369
1.58M
                    len += 255;
370
1.58M
                } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);
371
6.48k
            }
372
9.12k
            len += bytestream2_get_byte(gb) + 31;
373
9.12k
        }
374
179k
        pos = -bytestream2_get_byte(gb);
375
179k
        bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
376
179k
        bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos - (bytestream2_get_byte(gb) << 8), SEEK_SET);
377
179k
        if (bytestream2_tell_p(pb) == bytestream2_tell(&gbc))
378
138k
            break;
379
41.0k
        if (len < 5 || bytestream2_tell_p(pb) - bytestream2_tell(&gbc) < 4) {
380
3.68k
            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
381
3.68k
            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
382
3.68k
            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
383
37.4k
        } else {
384
37.4k
            bytestream2_put_le32(pb, bytestream2_get_le32(&gbc));
385
37.4k
            len--;
386
37.4k
        }
387
389M
        do {
388
389M
            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
389
389M
            len--;
390
389M
        } while (len && bytestream2_get_bytes_left(&gbc) > 0);
391
41.0k
    }
392
393
139k
    return 0;
394
139k
}
395
396
static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
397
                        int *got_frame, AVPacket *avpkt)
398
265k
{
399
265k
    FMVCContext *s = avctx->priv_data;
400
265k
    GetByteContext *gb = &s->gb;
401
265k
    PutByteContext *pb = &s->pb;
402
265k
    int ret, y, x;
403
265k
    int key_frame;
404
405
265k
    if (avpkt->size < 8)
406
100k
        return AVERROR_INVALIDDATA;
407
408
164k
    bytestream2_init(gb, avpkt->data, avpkt->size);
409
164k
    bytestream2_skip(gb, 2);
410
411
164k
    key_frame = !!bytestream2_get_le16(gb);
412
413
164k
    if (key_frame) {
414
148k
        const uint8_t *src;
415
148k
        unsigned type, size;
416
148k
        uint8_t *dst;
417
418
148k
        type = bytestream2_get_le16(gb);
419
148k
        size = bytestream2_get_le16(gb);
420
148k
        if (size > bytestream2_get_bytes_left(gb))
421
6.28k
            return AVERROR_INVALIDDATA;
422
423
142k
        bytestream2_init_writer(pb, s->buffer, s->buffer_size);
424
142k
        if (type == 1) {
425
138k
            decode_type1(gb, pb);
426
138k
        } else if (type == 2){
427
2.21k
            decode_type2(gb, pb);
428
2.21k
        } else {
429
1.14k
            avpriv_report_missing_feature(avctx, "Compression type %d", type);
430
1.14k
            return AVERROR_PATCHWELCOME;
431
1.14k
        }
432
433
141k
        if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
434
64
            return ret;
435
436
141k
        frame->flags |= AV_FRAME_FLAG_KEY;
437
141k
        frame->pict_type = AV_PICTURE_TYPE_I;
438
439
141k
        src = s->buffer;
440
141k
        dst = frame->data[0] + (avctx->height - 1) * frame->linesize[0];
441
1.00M
        for (y = 0; y < avctx->height; y++) {
442
998k
            memcpy(dst, src, avctx->width * s->bpp);
443
998k
            dst -= frame->linesize[0];
444
998k
            src += s->stride * 4;
445
998k
            if (bytestream2_tell_p(pb) < y*s->stride * 4)
446
136k
                break;
447
998k
        }
448
141k
    } else {
449
15.6k
        unsigned block, nb_blocks;
450
15.6k
        int type, k, l;
451
15.6k
        uint8_t *ssrc, *ddst;
452
15.6k
        const uint32_t *src;
453
15.6k
        uint32_t *dst;
454
455
1.15M
        for (block = 0; block < s->nb_blocks; block++)
456
1.14M
            s->blocks[block].xor = 0;
457
458
15.6k
        nb_blocks = bytestream2_get_le16(gb);
459
15.6k
        if (nb_blocks > s->nb_blocks)
460
1.17k
            return AVERROR_INVALIDDATA;
461
462
14.4k
        bytestream2_init_writer(pb, s->pbuffer, s->pbuffer_size);
463
464
14.4k
        type = bytestream2_get_le16(gb);
465
18.9k
        for (block = 0; block < nb_blocks; block++) {
466
13.9k
            unsigned size, offset;
467
13.9k
            int start = 0;
468
469
13.9k
            offset = bytestream2_get_le16(gb);
470
13.9k
            if (offset >= s->nb_blocks)
471
770
                return AVERROR_INVALIDDATA;
472
473
13.1k
            size = bytestream2_get_le16(gb);
474
13.1k
            if (size > bytestream2_get_bytes_left(gb))
475
691
                return AVERROR_INVALIDDATA;
476
477
12.4k
            start = bytestream2_tell_p(pb);
478
12.4k
            if (type == 1) {
479
221
                decode_type1(gb, pb);
480
12.2k
            } else if (type == 2){
481
11.6k
                decode_type2(gb, pb);
482
11.6k
            } else {
483
605
                avpriv_report_missing_feature(avctx, "Compression type %d", type);
484
605
                return AVERROR_PATCHWELCOME;
485
605
            }
486
487
11.8k
            if (s->blocks[offset].size * 4 != bytestream2_tell_p(pb) - start)
488
7.37k
                return AVERROR_INVALIDDATA;
489
490
4.46k
            s->blocks[offset].xor = 1;
491
4.46k
        }
492
493
5.02k
        src = (const uint32_t *)s->pbuffer;
494
5.02k
        dst = (uint32_t *)s->buffer;
495
496
46.0k
        for (block = 0, y = 0; y < s->yb; y++) {
497
41.0k
            int block_h = s->blocks[block].h;
498
41.0k
            uint32_t *rect = dst;
499
500
185k
            for (x = 0; x < s->xb; x++) {
501
144k
                int block_w = s->blocks[block].w;
502
144k
                uint32_t *row = dst;
503
504
144k
                block_h = s->blocks[block].h;
505
144k
                if (s->blocks[block].xor) {
506
243k
                    for (k = 0; k < block_h; k++) {
507
239k
                        uint32_t *column = dst;
508
10.2M
                        for (l = 0; l < block_w; l++)
509
9.97M
                            *dst++ ^= *src++;
510
239k
                        dst = &column[s->stride];
511
239k
                    }
512
4.39k
                }
513
144k
                dst = &row[block_w];
514
144k
                ++block;
515
144k
            }
516
41.0k
            dst = &rect[block_h * s->stride];
517
41.0k
        }
518
519
5.02k
        if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
520
27
            return ret;
521
522
4.99k
        frame->flags &= ~AV_FRAME_FLAG_KEY;
523
4.99k
        frame->pict_type = AV_PICTURE_TYPE_P;
524
525
4.99k
        ssrc = s->buffer;
526
4.99k
        ddst = frame->data[0] + (avctx->height - 1) * frame->linesize[0];
527
3.79M
        for (y = 0; y < avctx->height; y++) {
528
3.79M
            memcpy(ddst, ssrc, avctx->width * s->bpp);
529
3.79M
            ddst -= frame->linesize[0];
530
3.79M
            ssrc += s->stride * 4;
531
3.79M
        }
532
4.99k
    }
533
534
146k
    *got_frame = 1;
535
536
146k
    return avpkt->size;
537
164k
}
538
539
static av_cold int decode_init(AVCodecContext *avctx)
540
1.51k
{
541
1.51k
    FMVCContext *s = avctx->priv_data;
542
1.51k
    int i, j, m, block = 0, h = BLOCK_HEIGHT, w = BLOCK_WIDTH;
543
544
1.51k
    switch (avctx->bits_per_coded_sample) {
545
500
    case 16:
546
500
        avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
547
500
        break;
548
122
    case 24:
549
122
        avctx->pix_fmt = AV_PIX_FMT_BGR24;
550
122
        break;
551
758
    case 32:
552
758
        avctx->pix_fmt = AV_PIX_FMT_BGRA;
553
758
        break;
554
134
    default:
555
134
        av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n",
556
134
               avctx->bits_per_coded_sample);
557
134
        return AVERROR_INVALIDDATA;
558
1.51k
    }
559
560
1.38k
    s->stride = (avctx->width * avctx->bits_per_coded_sample + 31) / 32;
561
1.38k
    s->xb     = s->stride / BLOCK_WIDTH;
562
1.38k
    m         = s->stride % BLOCK_WIDTH;
563
1.38k
    if (m) {
564
1.36k
        if (m < 37) {
565
300
            w = m + BLOCK_WIDTH;
566
1.06k
        } else {
567
1.06k
            w = m;
568
1.06k
            s->xb++;
569
1.06k
        }
570
1.36k
    }
571
572
1.38k
    s->yb = avctx->height / BLOCK_HEIGHT;
573
1.38k
    m     = avctx->height % BLOCK_HEIGHT;
574
1.38k
    if (m) {
575
1.36k
        if (m < 49) {
576
330
            h = m + BLOCK_HEIGHT;
577
1.03k
        } else {
578
1.03k
            h = m;
579
1.03k
            s->yb++;
580
1.03k
        }
581
1.36k
    }
582
583
1.38k
    s->nb_blocks = s->xb * s->yb;
584
1.38k
    if (!s->nb_blocks)
585
8
        return AVERROR_INVALIDDATA;
586
1.37k
    s->blocks    = av_calloc(s->nb_blocks, sizeof(*s->blocks));
587
1.37k
    if (!s->blocks)
588
0
        return AVERROR(ENOMEM);
589
590
91.3k
    for (i = 0; i < s->yb; i++) {
591
416k
        for (j = 0; j < s->xb; j++) {
592
326k
            if (i != (s->yb - 1) || j != (s->xb - 1)) {
593
325k
                if (i == s->yb - 1) {
594
132k
                    s->blocks[block].w    = BLOCK_WIDTH;
595
132k
                    s->blocks[block].h    = h;
596
132k
                    s->blocks[block].size = BLOCK_WIDTH * h;
597
192k
                } else if (j == s->xb - 1) {
598
88.5k
                    s->blocks[block].w    = w;
599
88.5k
                    s->blocks[block].h    = BLOCK_HEIGHT;
600
88.5k
                    s->blocks[block].size = BLOCK_HEIGHT * w;
601
103k
                } else {
602
103k
                    s->blocks[block].w    = BLOCK_WIDTH;
603
103k
                    s->blocks[block].h    = BLOCK_HEIGHT;
604
103k
                    s->blocks[block].size = BLOCK_WIDTH * BLOCK_HEIGHT;
605
103k
                }
606
325k
            } else {
607
1.37k
                s->blocks[block].w    = w;
608
1.37k
                s->blocks[block].h    = h;
609
1.37k
                s->blocks[block].size = w * h;
610
1.37k
            }
611
326k
            block++;
612
326k
        }
613
89.9k
    }
614
615
1.37k
    s->bpp          = avctx->bits_per_coded_sample >> 3;
616
1.37k
    s->buffer_size  = avctx->width * avctx->height * 4;
617
1.37k
    s->pbuffer_size = avctx->width * avctx->height * 4;
618
1.37k
    s->buffer       = av_mallocz(s->buffer_size);
619
1.37k
    s->pbuffer      = av_mallocz(s->pbuffer_size);
620
1.37k
    if (!s->buffer || !s->pbuffer)
621
0
        return AVERROR(ENOMEM);
622
623
1.37k
    return 0;
624
1.37k
}
625
626
static av_cold int decode_close(AVCodecContext *avctx)
627
1.51k
{
628
1.51k
    FMVCContext *s = avctx->priv_data;
629
630
1.51k
    av_freep(&s->buffer);
631
1.51k
    av_freep(&s->pbuffer);
632
1.51k
    av_freep(&s->blocks);
633
634
1.51k
    return 0;
635
1.51k
}
636
637
const FFCodec ff_fmvc_decoder = {
638
    .p.name           = "fmvc",
639
    CODEC_LONG_NAME("FM Screen Capture Codec"),
640
    .p.type           = AVMEDIA_TYPE_VIDEO,
641
    .p.id             = AV_CODEC_ID_FMVC,
642
    .priv_data_size   = sizeof(FMVCContext),
643
    .init             = decode_init,
644
    .close            = decode_close,
645
    FF_CODEC_DECODE_CB(decode_frame),
646
    .p.capabilities   = AV_CODEC_CAP_DR1,
647
    .caps_internal    = FF_CODEC_CAP_INIT_CLEANUP,
648
};