GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/fmvc.c Lines: 335 390 85.9 %
Date: 2019-11-18 18:00:01 Branches: 174 228 76.3 %

Line Branch Exec 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 <stdlib.h>
25
#include <string.h>
26
27
#include "avcodec.h"
28
#include "bytestream.h"
29
#include "internal.h"
30
31
#define BLOCK_HEIGHT 112u
32
#define BLOCK_WIDTH  84u
33
34
typedef struct InterBlock {
35
    int      w, h;
36
    int      size;
37
    int      xor;
38
} InterBlock;
39
40
typedef struct FMVCContext {
41
    GetByteContext  gb;
42
    PutByteContext  pb;
43
    uint8_t        *buffer;
44
    size_t          buffer_size;
45
    uint8_t        *pbuffer;
46
    size_t          pbuffer_size;
47
    ptrdiff_t       stride;
48
    int             bpp;
49
    int             yb, xb;
50
    InterBlock     *blocks;
51
    unsigned        nb_blocks;
52
} FMVCContext;
53
54
72
static int decode_type2(GetByteContext *gb, PutByteContext *pb)
55
{
56
72
    unsigned repeat = 0, first = 1, opcode = 0;
57
    int i, len, pos;
58
59
4593
    while (bytestream2_get_bytes_left(gb) > 0) {
60
        GetByteContext gbc;
61
62
33101
        while (bytestream2_get_bytes_left(gb) > 0) {
63
33101
            if (first) {
64
72
                first = 0;
65
72
                if (bytestream2_peek_byte(gb) > 17) {
66
72
                    len = bytestream2_get_byte(gb) - 17;
67
72
                    if (len < 4) {
68
                        do {
69
65
                            bytestream2_put_byte(pb, bytestream2_get_byte(gb));
70
65
                            --len;
71
65
                        } while (len);
72
65
                        opcode = bytestream2_peek_byte(gb);
73
65
                        continue;
74
                    } else {
75
                        do {
76
103
                            bytestream2_put_byte(pb, bytestream2_get_byte(gb));
77
103
                            --len;
78
103
                        } while (len);
79
7
                        opcode = bytestream2_peek_byte(gb);
80
7
                        if (opcode < 0x10) {
81
                            bytestream2_skip(gb, 1);
82
                            pos = - (opcode >> 2) - 4 * bytestream2_get_byte(gb) - 2049;
83
84
                            bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
85
                            bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
86
87
                            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
88
                            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
89
                            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
90
                            len = opcode & 3;
91
                            if (!len) {
92
                                repeat = 1;
93
                            } else {
94
                                do {
95
                                    bytestream2_put_byte(pb, bytestream2_get_byte(gb));
96
                                    --len;
97
                                } while (len);
98
                                opcode = bytestream2_peek_byte(gb);
99
                            }
100
                            continue;
101
                        }
102
                    }
103
7
                    repeat = 0;
104
                }
105
7
                repeat = 1;
106
            }
107
33036
            if (repeat) {
108
26608
                repeat = 0;
109
26608
                opcode = bytestream2_peek_byte(gb);
110
26608
                if (opcode < 0x10) {
111
586
                    bytestream2_skip(gb, 1);
112
586
                    if (!opcode) {
113
82
                        if (!bytestream2_peek_byte(gb)) {
114
                            do {
115
                                bytestream2_skip(gb, 1);
116
                                opcode += 255;
117
                            } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);
118
                        }
119
82
                        opcode += bytestream2_get_byte(gb) + 15;
120
                    }
121
586
                    bytestream2_put_le32(pb, bytestream2_get_le32(gb));
122
4212
                    for (i = opcode - 1; i > 0; --i)
123
3626
                        bytestream2_put_byte(pb, bytestream2_get_byte(gb));
124
586
                    opcode = bytestream2_peek_byte(gb);
125
586
                    if (opcode < 0x10) {
126
28
                        bytestream2_skip(gb, 1);
127
28
                        pos = - (opcode >> 2) - 4 * bytestream2_get_byte(gb) - 2049;
128
129
28
                        bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
130
28
                        bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
131
132
28
                        bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
133
28
                        bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
134
28
                        bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
135
28
                        len = opcode & 3;
136
28
                        if (!len) {
137
22
                            repeat = 1;
138
                        } else {
139
                            do {
140
17
                                bytestream2_put_byte(pb, bytestream2_get_byte(gb));
141
17
                                --len;
142
17
                            } while (len);
143
6
                            opcode = bytestream2_peek_byte(gb);
144
                        }
145
28
                        continue;
146
                    }
147
                }
148
            }
149
150
33008
            if (opcode >= 0x40) {
151
6293
                bytestream2_skip(gb, 1);
152
6293
                pos = - ((opcode >> 2) & 7) - 1 - 8 * bytestream2_get_byte(gb);
153
6293
                len =    (opcode >> 5)      - 1;
154
155
6293
                bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
156
6293
                bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
157
158
6293
                bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
159
6293
                bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
160
                do {
161
15169
                    bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
162
15169
                    --len;
163
15169
                } while (len);
164
165
6293
                len = opcode & 3;
166
167
6293
                if (!len) {
168
3620
                    repeat = 1;
169
                } else {
170
                    do {
171
4856
                        bytestream2_put_byte(pb, bytestream2_get_byte(gb));
172
4856
                        --len;
173
4856
                    } while (len);
174
2673
                    opcode = bytestream2_peek_byte(gb);
175
                }
176
6293
                continue;
177
26715
            } else if (opcode < 0x20) {
178
4593
                break;
179
            }
180
22122
            len = opcode & 0x1F;
181
22122
            bytestream2_skip(gb, 1);
182
22122
            if (!len) {
183
7443
                if (!bytestream2_peek_byte(gb)) {
184
                    do {
185
9973
                        bytestream2_skip(gb, 1);
186
9973
                        len += 255;
187

9973
                    } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);
188
                }
189
7443
                len += bytestream2_get_byte(gb) + 31;
190
            }
191
22122
            i = bytestream2_get_le16(gb);
192
22122
            pos = - (i >> 2) - 1;
193
194
22122
            bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
195
22122
            bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
196
197

22122
            if (len < 6 || bytestream2_tell_p(pb) - bytestream2_tell(&gbc) < 4) {
198
3050
                bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
199
3050
                bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
200
                do {
201
1990991
                    bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
202
1990991
                    --len;
203
1990991
                } while (len);
204
            } else {
205
19072
                bytestream2_put_le32(pb, bytestream2_get_le32(&gbc));
206
1700600
                for (len = len - 2; len; --len)
207
1681528
                    bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
208
            }
209
22122
            len = i & 3;
210
22122
            if (!len) {
211
19401
                repeat = 1;
212
            } else {
213
                do {
214
5082
                    bytestream2_put_byte(pb, bytestream2_get_byte(gb));
215
5082
                    --len;
216
5082
                } while (len);
217
2721
                opcode = bytestream2_peek_byte(gb);
218
            }
219
        }
220
4593
        bytestream2_skip(gb, 1);
221
4593
        if (opcode < 0x10) {
222
998
            pos = -(opcode >> 2) - 1 - 4 * bytestream2_get_byte(gb);
223
224
998
            bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
225
998
            bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
226
227
998
            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
228
998
            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
229
998
            len = opcode & 3;
230
998
            if (!len) {
231
371
                repeat = 1;
232
            } else {
233
                do {
234
1101
                    bytestream2_put_byte(pb, bytestream2_get_byte(gb));
235
1101
                    --len;
236
1101
                } while (len);
237
627
                opcode = bytestream2_peek_byte(gb);
238
            }
239
998
            continue;
240
        }
241
3595
        len = opcode & 7;
242
3595
        if (!len) {
243
3085
            if (!bytestream2_peek_byte(gb)) {
244
                do {
245
411
                    bytestream2_skip(gb, 1);
246
411
                    len += 255;
247

411
                } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);
248
            }
249
3085
            len += bytestream2_get_byte(gb) + 7;
250
        }
251
3595
        i = bytestream2_get_le16(gb);
252
3595
        pos = bytestream2_tell_p(pb) - 2048 * (opcode & 8);
253
3595
        pos = pos - (i >> 2);
254
3595
        if (pos == bytestream2_tell_p(pb))
255
72
            break;
256
257
3523
        pos = pos - 0x4000;
258
3523
        bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
259
3523
        bytestream2_seek(&gbc, pos, SEEK_SET);
260
261

3523
        if (len < 6 || bytestream2_tell_p(pb) - bytestream2_tell(&gbc) < 4) {
262
216
            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
263
216
            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
264
            do {
265
667
                bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
266
667
                --len;
267
667
            } while (len);
268
        } else {
269
3307
            bytestream2_put_le32(pb, bytestream2_get_le32(&gbc));
270
219261
            for (len = len - 2; len; --len)
271
215954
                bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
272
        }
273
274
3523
        len = i & 3;
275
3523
        if (!len) {
276
3187
            repeat = 1;
277
        } else {
278
            do {
279
551
                bytestream2_put_byte(pb, bytestream2_get_byte(gb));
280
551
                --len;
281
551
            } while (len);
282
336
            opcode = bytestream2_peek_byte(gb);
283
        }
284
    }
285
286
72
    return 0;
287
}
288
289
42
static int decode_type1(GetByteContext *gb, PutByteContext *pb)
290
{
291
42
    unsigned opcode = 0, len;
292
42
    int high = 0;
293
    int i, pos;
294
295
10429
    while (bytestream2_get_bytes_left(gb) > 0) {
296
        GetByteContext gbc;
297
298
21442
        while (bytestream2_get_bytes_left(gb) > 0) {
299
21442
            while (bytestream2_get_bytes_left(gb) > 0) {
300
21442
                opcode = bytestream2_get_byte(gb);
301
21442
                high = opcode >= 0x20;
302
21442
                if (high)
303
18221
                    break;
304
3221
                if (opcode)
305
3220
                    break;
306
1
                opcode = bytestream2_get_byte(gb);
307
1
                if (opcode < 0xF8) {
308
1
                    opcode += 32;
309
1
                    break;
310
                }
311
                i = opcode - 0xF8;
312
                if (i) {
313
                    len = 256;
314
                    do {
315
                        len *= 2;
316
                        --i;
317
                    } while (i);
318
                } else {
319
                    len = 280;
320
                }
321
                do {
322
                    bytestream2_put_le32(pb, bytestream2_get_le32(gb));
323
                    bytestream2_put_le32(pb, bytestream2_get_le32(gb));
324
                    len -= 8;
325
                } while (len && bytestream2_get_bytes_left(gb) > 0);
326
            }
327
328
21442
            if (!high) {
329
                do {
330
11005
                    bytestream2_put_byte(pb, bytestream2_get_byte(gb));
331
11005
                    --opcode;
332

11005
                } while (opcode && bytestream2_get_bytes_left(gb) > 0);
333
334
3223
                while (bytestream2_get_bytes_left(gb) > 0) {
335
                    GetByteContext gbc;
336
337
3223
                    opcode = bytestream2_get_byte(gb);
338
3223
                    if (opcode >= 0x20)
339
3221
                        break;
340
2
                    bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
341
342
2
                    pos = -(opcode | 32 * bytestream2_get_byte(gb)) - 1;
343
2
                    bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
344
2
                    bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
345
2
                    bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
346
2
                    bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
347
2
                    bytestream2_put_byte(pb, bytestream2_get_byte(gb));
348
                }
349
            }
350
21442
            high = 0;
351
21442
            if (opcode < 0x40)
352
10429
                break;
353
11013
            bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
354
11013
            pos = (-((opcode & 0x1F) | 32 * bytestream2_get_byte(gb)) - 1);
355
11013
            bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
356
11013
            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
357
11013
            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
358
11013
            len = (opcode >> 5) - 1;
359
            do {
360
35434
                bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
361
35434
                --len;
362

35434
            } while (len && bytestream2_get_bytes_left(&gbc) > 0);
363
        }
364
10429
        len = opcode & 0x1F;
365
10429
        if (!len) {
366
3296
            if (!bytestream2_peek_byte(gb)) {
367
                do {
368
7405
                    bytestream2_skip(gb, 1);
369
7405
                    len += 255;
370

7405
                } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);
371
            }
372
3296
            len += bytestream2_get_byte(gb) + 31;
373
        }
374
10429
        pos = -bytestream2_get_byte(gb);
375
10429
        bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
376
10429
        bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos - (bytestream2_get_byte(gb) << 8), SEEK_SET);
377
10429
        if (bytestream2_tell_p(pb) == bytestream2_tell(&gbc))
378
42
            break;
379

10387
        if (len < 5 || bytestream2_tell_p(pb) - bytestream2_tell(&gbc) < 4) {
380
1068
            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
381
1068
            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
382
1068
            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
383
        } else {
384
9319
            bytestream2_put_le32(pb, bytestream2_get_le32(&gbc));
385
9319
            len--;
386
        }
387
        do {
388
2411287
            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
389
2411287
            len--;
390

2411287
        } while (len && bytestream2_get_bytes_left(&gbc) > 0);
391
    }
392
393
42
    return 0;
394
}
395
396
34
static int decode_frame(AVCodecContext *avctx, void *data,
397
                        int *got_frame, AVPacket *avpkt)
398
{
399
34
    FMVCContext *s = avctx->priv_data;
400
34
    GetByteContext *gb = &s->gb;
401
34
    PutByteContext *pb = &s->pb;
402
34
    AVFrame *frame = data;
403
    int ret, y, x;
404
405
34
    if (avpkt->size < 8)
406
        return AVERROR_INVALIDDATA;
407
408
34
    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
409
        return ret;
410
411
34
    bytestream2_init(gb, avpkt->data, avpkt->size);
412
34
    bytestream2_skip(gb, 2);
413
414
34
    frame->key_frame = !!bytestream2_get_le16(gb);
415
34
    frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
416
417
34
    if (frame->key_frame) {
418
        const uint8_t *src;
419
        unsigned type, size;
420
        uint8_t *dst;
421
422
2
        type = bytestream2_get_le16(gb);
423
2
        size = bytestream2_get_le16(gb);
424
2
        if (size > bytestream2_get_bytes_left(gb))
425
            return AVERROR_INVALIDDATA;
426
427
2
        bytestream2_init_writer(pb, s->buffer, s->buffer_size);
428
2
        if (type == 1) {
429
1
            decode_type1(gb, pb);
430
1
        } else if (type == 2){
431
1
            decode_type2(gb, pb);
432
        } else {
433
            avpriv_report_missing_feature(avctx, "Compression type %d", type);
434
            return AVERROR_PATCHWELCOME;
435
        }
436
437
2
        src = s->buffer;
438
2
        dst = frame->data[0] + (avctx->height - 1) * frame->linesize[0];
439
960
        for (y = 0; y < avctx->height; y++) {
440
958
            memcpy(dst, src, avctx->width * s->bpp);
441
958
            dst -= frame->linesize[0];
442
958
            src += s->stride * 4;
443
        }
444
    } else {
445
        unsigned block, nb_blocks;
446
        int type, k, l;
447
        uint8_t *ssrc, *ddst;
448
        const uint32_t *src;
449
        uint32_t *dst;
450
451
1067
        for (block = 0; block < s->nb_blocks; block++)
452
1035
            s->blocks[block].xor = 0;
453
454
32
        nb_blocks = bytestream2_get_le16(gb);
455
32
        if (nb_blocks > s->nb_blocks)
456
            return AVERROR_INVALIDDATA;
457
458
32
        bytestream2_init_writer(pb, s->pbuffer, s->pbuffer_size);
459
460
32
        type = bytestream2_get_le16(gb);
461
144
        for (block = 0; block < nb_blocks; block++) {
462
            unsigned size, offset;
463
112
            int start = 0;
464
465
112
            offset = bytestream2_get_le16(gb);
466
112
            if (offset >= s->nb_blocks)
467
                return AVERROR_INVALIDDATA;
468
469
112
            size = bytestream2_get_le16(gb);
470
112
            if (size > bytestream2_get_bytes_left(gb))
471
                return AVERROR_INVALIDDATA;
472
473
112
            start = bytestream2_tell_p(pb);
474
112
            if (type == 1) {
475
41
                decode_type1(gb, pb);
476
71
            } else if (type == 2){
477
71
                decode_type2(gb, pb);
478
            } else {
479
                avpriv_report_missing_feature(avctx, "Compression type %d", type);
480
                return AVERROR_PATCHWELCOME;
481
            }
482
483
112
            if (s->blocks[offset].size * 4 != bytestream2_tell_p(pb) - start)
484
                return AVERROR_INVALIDDATA;
485
486
112
            s->blocks[offset].xor = 1;
487
        }
488
489
32
        src = (const uint32_t *)s->pbuffer;
490
32
        dst = (uint32_t *)s->buffer;
491
492
182
        for (block = 0, y = 0; y < s->yb; y++) {
493
150
            int block_h = s->blocks[block].h;
494
150
            uint32_t *rect = dst;
495
496
1185
            for (x = 0; x < s->xb; x++) {
497
1035
                int block_w = s->blocks[block].w;
498
1035
                uint32_t *row = dst;
499
500
1035
                block_h = s->blocks[block].h;
501
1035
                if (s->blocks[block].xor) {
502
13668
                    for (k = 0; k < block_h; k++) {
503
13556
                        uint32_t *column = dst;
504
1129796
                        for (l = 0; l < block_w; l++)
505
1116240
                            *dst++ ^= *src++;
506
13556
                        dst = &column[s->stride];
507
                    }
508
                }
509
1035
                dst = &row[block_w];
510
1035
                ++block;
511
            }
512
150
            dst = &rect[block_h * s->stride];
513
        }
514
515
32
        ssrc = s->buffer;
516
32
        ddst = frame->data[0] + (avctx->height - 1) * frame->linesize[0];
517
17494
        for (y = 0; y < avctx->height; y++) {
518
17462
            memcpy(ddst, ssrc, avctx->width * s->bpp);
519
17462
            ddst -= frame->linesize[0];
520
17462
            ssrc += s->stride * 4;
521
        }
522
    }
523
524
34
    *got_frame = 1;
525
526
34
    return avpkt->size;
527
}
528
529
4
static av_cold int decode_init(AVCodecContext *avctx)
530
{
531
4
    FMVCContext *s = avctx->priv_data;
532
4
    int i, j, m, block = 0, h = BLOCK_HEIGHT, w = BLOCK_WIDTH;
533
534

4
    switch (avctx->bits_per_coded_sample) {
535
    case 16:
536
        avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
537
        break;
538
4
    case 24:
539
4
        avctx->pix_fmt = AV_PIX_FMT_BGR24;
540
4
        break;
541
    case 32:
542
        avctx->pix_fmt = AV_PIX_FMT_BGRA;
543
        break;
544
    default:
545
        av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n",
546
               avctx->bits_per_coded_sample);
547
        return AVERROR_INVALIDDATA;
548
    }
549
550
4
    s->stride = (avctx->width * avctx->bits_per_coded_sample + 31) / 32;
551
4
    s->xb     = s->stride / BLOCK_WIDTH;
552
4
    m         = s->stride % BLOCK_WIDTH;
553
4
    if (m) {
554
4
        if (m < 37) {
555
            w = m + BLOCK_WIDTH;
556
        } else {
557
4
            w = m;
558
4
            s->xb++;
559
        }
560
    }
561
562
4
    s->yb = avctx->height / BLOCK_HEIGHT;
563
4
    m     = avctx->height % BLOCK_HEIGHT;
564
4
    if (m) {
565
4
        if (m < 49) {
566
4
            h = m + BLOCK_HEIGHT;
567
        } else {
568
            h = m;
569
            s->yb++;
570
        }
571
    }
572
573
4
    s->nb_blocks = s->xb * s->yb;
574
4
    if (!s->nb_blocks)
575
        return AVERROR_INVALIDDATA;
576
4
    s->blocks    = av_calloc(s->nb_blocks, sizeof(*s->blocks));
577
4
    if (!s->blocks)
578
        return AVERROR(ENOMEM);
579
580
20
    for (i = 0; i < s->yb; i++) {
581
122
        for (j = 0; j < s->xb; j++) {
582

106
            if (i != (s->yb - 1) || j != (s->xb - 1)) {
583
102
                if (i == s->yb - 1) {
584
22
                    s->blocks[block].w    = BLOCK_WIDTH;
585
22
                    s->blocks[block].h    = h;
586
22
                    s->blocks[block].size = BLOCK_WIDTH * h;
587
80
                } else if (j == s->xb - 1) {
588
12
                    s->blocks[block].w    = w;
589
12
                    s->blocks[block].h    = BLOCK_HEIGHT;
590
12
                    s->blocks[block].size = BLOCK_HEIGHT * w;
591
                } else {
592
68
                    s->blocks[block].w    = BLOCK_WIDTH;
593
68
                    s->blocks[block].h    = BLOCK_HEIGHT;
594
68
                    s->blocks[block].size = BLOCK_WIDTH * BLOCK_HEIGHT;
595
                }
596
            } else {
597
4
                s->blocks[block].w    = w;
598
4
                s->blocks[block].h    = h;
599
4
                s->blocks[block].size = w * h;
600
            }
601
106
            block++;
602
        }
603
    }
604
605
4
    s->bpp          = avctx->bits_per_coded_sample >> 3;
606
4
    s->buffer_size  = avctx->width * avctx->height * 4;
607
4
    s->pbuffer_size = avctx->width * avctx->height * 4;
608
4
    s->buffer       = av_mallocz(s->buffer_size);
609
4
    s->pbuffer      = av_mallocz(s->pbuffer_size);
610

4
    if (!s->buffer || !s->pbuffer)
611
        return AVERROR(ENOMEM);
612
613
4
    return 0;
614
}
615
616
4
static av_cold int decode_close(AVCodecContext *avctx)
617
{
618
4
    FMVCContext *s = avctx->priv_data;
619
620
4
    av_freep(&s->buffer);
621
4
    av_freep(&s->pbuffer);
622
4
    av_freep(&s->blocks);
623
624
4
    return 0;
625
}
626
627
AVCodec ff_fmvc_decoder = {
628
    .name             = "fmvc",
629
    .long_name        = NULL_IF_CONFIG_SMALL("FM Screen Capture Codec"),
630
    .type             = AVMEDIA_TYPE_VIDEO,
631
    .id               = AV_CODEC_ID_FMVC,
632
    .priv_data_size   = sizeof(FMVCContext),
633
    .init             = decode_init,
634
    .close            = decode_close,
635
    .decode           = decode_frame,
636
    .capabilities     = AV_CODEC_CAP_DR1,
637
    .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE |
638
                        FF_CODEC_CAP_INIT_CLEANUP,
639
};