FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/fmvc.c
Date: 2022-11-28 23:49:43
Exec Total Coverage
Lines: 339 396 85.6%
Branches: 174 230 75.7%

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 <string.h>
25
26 #include "avcodec.h"
27 #include "bytestream.h"
28 #include "codec_internal.h"
29 #include "decode.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
1/2
✓ Branch 1 taken 4593 times.
✗ Branch 2 not taken.
4593 while (bytestream2_get_bytes_left(gb) > 0) {
60 GetByteContext gbc;
61
62
1/2
✓ Branch 1 taken 33101 times.
✗ Branch 2 not taken.
33101 while (bytestream2_get_bytes_left(gb) > 0) {
63
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 33029 times.
33101 if (first) {
64 72 first = 0;
65
1/2
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
72 if (bytestream2_peek_byte(gb) > 17) {
66 72 len = bytestream2_get_byte(gb) - 17;
67
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 7 times.
72 if (len < 4) {
68 do {
69 65 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
70 65 --len;
71
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
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
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 7 times.
103 } while (len);
79 7 opcode = bytestream2_peek_byte(gb);
80
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
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
2/2
✓ Branch 0 taken 26608 times.
✓ Branch 1 taken 6428 times.
33036 if (repeat) {
108 26608 repeat = 0;
109 26608 opcode = bytestream2_peek_byte(gb);
110
2/2
✓ Branch 0 taken 586 times.
✓ Branch 1 taken 26022 times.
26608 if (opcode < 0x10) {
111 586 bytestream2_skip(gb, 1);
112
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 504 times.
586 if (!opcode) {
113
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 82 times.
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
2/2
✓ Branch 0 taken 3626 times.
✓ Branch 1 taken 586 times.
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
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 558 times.
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
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 6 times.
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
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 6 times.
17 } while (len);
143 6 opcode = bytestream2_peek_byte(gb);
144 }
145 28 continue;
146 }
147 }
148 }
149
150
2/2
✓ Branch 0 taken 6293 times.
✓ Branch 1 taken 26715 times.
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
2/2
✓ Branch 0 taken 8876 times.
✓ Branch 1 taken 6293 times.
15169 } while (len);
164
165 6293 len = opcode & 3;
166
167
2/2
✓ Branch 0 taken 3620 times.
✓ Branch 1 taken 2673 times.
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
2/2
✓ Branch 0 taken 2183 times.
✓ Branch 1 taken 2673 times.
4856 } while (len);
174 2673 opcode = bytestream2_peek_byte(gb);
175 }
176 6293 continue;
177
2/2
✓ Branch 0 taken 4593 times.
✓ Branch 1 taken 22122 times.
26715 } else if (opcode < 0x20) {
178 4593 break;
179 }
180 22122 len = opcode & 0x1F;
181 22122 bytestream2_skip(gb, 1);
182
2/2
✓ Branch 0 taken 7443 times.
✓ Branch 1 taken 14679 times.
22122 if (!len) {
183
2/2
✓ Branch 1 taken 2416 times.
✓ Branch 2 taken 5027 times.
7443 if (!bytestream2_peek_byte(gb)) {
184 do {
185 9973 bytestream2_skip(gb, 1);
186 9973 len += 255;
187
3/4
✓ Branch 1 taken 7557 times.
✓ Branch 2 taken 2416 times.
✓ Branch 4 taken 7557 times.
✗ Branch 5 not taken.
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
4/4
✓ Branch 0 taken 20962 times.
✓ Branch 1 taken 1160 times.
✓ Branch 4 taken 1890 times.
✓ Branch 5 taken 19072 times.
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
2/2
✓ Branch 0 taken 1987941 times.
✓ Branch 1 taken 3050 times.
1990991 } while (len);
204 } else {
205 19072 bytestream2_put_le32(pb, bytestream2_get_le32(&gbc));
206
2/2
✓ Branch 0 taken 1681528 times.
✓ Branch 1 taken 19072 times.
1700600 for (len = len - 2; len; --len)
207 1681528 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
208 }
209 22122 len = i & 3;
210
2/2
✓ Branch 0 taken 19401 times.
✓ Branch 1 taken 2721 times.
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
2/2
✓ Branch 0 taken 2361 times.
✓ Branch 1 taken 2721 times.
5082 } while (len);
217 2721 opcode = bytestream2_peek_byte(gb);
218 }
219 }
220 4593 bytestream2_skip(gb, 1);
221
2/2
✓ Branch 0 taken 998 times.
✓ Branch 1 taken 3595 times.
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
2/2
✓ Branch 0 taken 371 times.
✓ Branch 1 taken 627 times.
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
2/2
✓ Branch 0 taken 474 times.
✓ Branch 1 taken 627 times.
1101 } while (len);
237 627 opcode = bytestream2_peek_byte(gb);
238 }
239 998 continue;
240 }
241 3595 len = opcode & 7;
242
2/2
✓ Branch 0 taken 3085 times.
✓ Branch 1 taken 510 times.
3595 if (!len) {
243
2/2
✓ Branch 1 taken 154 times.
✓ Branch 2 taken 2931 times.
3085 if (!bytestream2_peek_byte(gb)) {
244 do {
245 411 bytestream2_skip(gb, 1);
246 411 len += 255;
247
3/4
✓ Branch 1 taken 257 times.
✓ Branch 2 taken 154 times.
✓ Branch 4 taken 257 times.
✗ Branch 5 not taken.
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
2/2
✓ Branch 1 taken 72 times.
✓ Branch 2 taken 3523 times.
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
3/4
✓ Branch 0 taken 3307 times.
✓ Branch 1 taken 216 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3307 times.
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
2/2
✓ Branch 0 taken 451 times.
✓ Branch 1 taken 216 times.
667 } while (len);
268 } else {
269 3307 bytestream2_put_le32(pb, bytestream2_get_le32(&gbc));
270
2/2
✓ Branch 0 taken 215954 times.
✓ Branch 1 taken 3307 times.
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
2/2
✓ Branch 0 taken 3187 times.
✓ Branch 1 taken 336 times.
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
2/2
✓ Branch 0 taken 215 times.
✓ Branch 1 taken 336 times.
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
1/2
✓ Branch 1 taken 10429 times.
✗ Branch 2 not taken.
10429 while (bytestream2_get_bytes_left(gb) > 0) {
296 GetByteContext gbc;
297
298
1/2
✓ Branch 1 taken 21442 times.
✗ Branch 2 not taken.
21442 while (bytestream2_get_bytes_left(gb) > 0) {
299
1/2
✓ Branch 1 taken 21442 times.
✗ Branch 2 not taken.
21442 while (bytestream2_get_bytes_left(gb) > 0) {
300 21442 opcode = bytestream2_get_byte(gb);
301 21442 high = opcode >= 0x20;
302
2/2
✓ Branch 0 taken 18221 times.
✓ Branch 1 taken 3221 times.
21442 if (high)
303 18221 break;
304
2/2
✓ Branch 0 taken 3220 times.
✓ Branch 1 taken 1 times.
3221 if (opcode)
305 3220 break;
306 1 opcode = bytestream2_get_byte(gb);
307
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
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
2/2
✓ Branch 0 taken 3221 times.
✓ Branch 1 taken 18221 times.
21442 if (!high) {
329 do {
330 11005 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
331 11005 --opcode;
332
3/4
✓ Branch 0 taken 7784 times.
✓ Branch 1 taken 3221 times.
✓ Branch 3 taken 7784 times.
✗ Branch 4 not taken.
11005 } while (opcode && bytestream2_get_bytes_left(gb) > 0);
333
334
1/2
✓ Branch 1 taken 3223 times.
✗ Branch 2 not taken.
3223 while (bytestream2_get_bytes_left(gb) > 0) {
335 GetByteContext gbc;
336
337 3223 opcode = bytestream2_get_byte(gb);
338
2/2
✓ Branch 0 taken 3221 times.
✓ Branch 1 taken 2 times.
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
2/2
✓ Branch 0 taken 10429 times.
✓ Branch 1 taken 11013 times.
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
3/4
✓ Branch 0 taken 24421 times.
✓ Branch 1 taken 11013 times.
✓ Branch 3 taken 24421 times.
✗ Branch 4 not taken.
35434 } while (len && bytestream2_get_bytes_left(&gbc) > 0);
363 }
364 10429 len = opcode & 0x1F;
365
2/2
✓ Branch 0 taken 3296 times.
✓ Branch 1 taken 7133 times.
10429 if (!len) {
366
2/2
✓ Branch 1 taken 1486 times.
✓ Branch 2 taken 1810 times.
3296 if (!bytestream2_peek_byte(gb)) {
367 do {
368 7405 bytestream2_skip(gb, 1);
369 7405 len += 255;
370
3/4
✓ Branch 1 taken 5919 times.
✓ Branch 2 taken 1486 times.
✓ Branch 4 taken 5919 times.
✗ Branch 5 not taken.
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
2/2
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 10387 times.
10429 if (bytestream2_tell_p(pb) == bytestream2_tell(&gbc))
378 42 break;
379
4/4
✓ Branch 0 taken 9497 times.
✓ Branch 1 taken 890 times.
✓ Branch 4 taken 178 times.
✓ Branch 5 taken 9319 times.
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
3/4
✓ Branch 0 taken 2400900 times.
✓ Branch 1 taken 10387 times.
✓ Branch 3 taken 2400900 times.
✗ Branch 4 not taken.
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, AVFrame *frame,
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 int ret, y, x;
403 int key_frame;
404
405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (avpkt->size < 8)
406 return AVERROR_INVALIDDATA;
407
408 34 bytestream2_init(gb, avpkt->data, avpkt->size);
409 34 bytestream2_skip(gb, 2);
410
411 34 key_frame = !!bytestream2_get_le16(gb);
412
413
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 32 times.
34 if (key_frame) {
414 const uint8_t *src;
415 unsigned type, size;
416 uint8_t *dst;
417
418 2 type = bytestream2_get_le16(gb);
419 2 size = bytestream2_get_le16(gb);
420
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (size > bytestream2_get_bytes_left(gb))
421 return AVERROR_INVALIDDATA;
422
423 2 bytestream2_init_writer(pb, s->buffer, s->buffer_size);
424
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (type == 1) {
425 1 decode_type1(gb, pb);
426
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 } else if (type == 2){
427 1 decode_type2(gb, pb);
428 } else {
429 avpriv_report_missing_feature(avctx, "Compression type %d", type);
430 return AVERROR_PATCHWELCOME;
431 }
432
433
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
434 return ret;
435
436 2 frame->key_frame = 1;
437 2 frame->pict_type = AV_PICTURE_TYPE_I;
438
439 2 src = s->buffer;
440 2 dst = frame->data[0] + (avctx->height - 1) * frame->linesize[0];
441
2/2
✓ Branch 0 taken 958 times.
✓ Branch 1 taken 2 times.
960 for (y = 0; y < avctx->height; y++) {
442 958 memcpy(dst, src, avctx->width * s->bpp);
443 958 dst -= frame->linesize[0];
444 958 src += s->stride * 4;
445
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 958 times.
958 if (bytestream2_tell_p(pb) < y*s->stride * 4)
446 break;
447 }
448 } else {
449 unsigned block, nb_blocks;
450 int type, k, l;
451 uint8_t *ssrc, *ddst;
452 const uint32_t *src;
453 uint32_t *dst;
454
455
2/2
✓ Branch 0 taken 1035 times.
✓ Branch 1 taken 32 times.
1067 for (block = 0; block < s->nb_blocks; block++)
456 1035 s->blocks[block].xor = 0;
457
458 32 nb_blocks = bytestream2_get_le16(gb);
459
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (nb_blocks > s->nb_blocks)
460 return AVERROR_INVALIDDATA;
461
462 32 bytestream2_init_writer(pb, s->pbuffer, s->pbuffer_size);
463
464 32 type = bytestream2_get_le16(gb);
465
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 32 times.
144 for (block = 0; block < nb_blocks; block++) {
466 unsigned size, offset;
467 112 int start = 0;
468
469 112 offset = bytestream2_get_le16(gb);
470
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (offset >= s->nb_blocks)
471 return AVERROR_INVALIDDATA;
472
473 112 size = bytestream2_get_le16(gb);
474
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
112 if (size > bytestream2_get_bytes_left(gb))
475 return AVERROR_INVALIDDATA;
476
477 112 start = bytestream2_tell_p(pb);
478
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 71 times.
112 if (type == 1) {
479 41 decode_type1(gb, pb);
480
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 } else if (type == 2){
481 71 decode_type2(gb, pb);
482 } else {
483 avpriv_report_missing_feature(avctx, "Compression type %d", type);
484 return AVERROR_PATCHWELCOME;
485 }
486
487
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
112 if (s->blocks[offset].size * 4 != bytestream2_tell_p(pb) - start)
488 return AVERROR_INVALIDDATA;
489
490 112 s->blocks[offset].xor = 1;
491 }
492
493 32 src = (const uint32_t *)s->pbuffer;
494 32 dst = (uint32_t *)s->buffer;
495
496
2/2
✓ Branch 0 taken 150 times.
✓ Branch 1 taken 32 times.
182 for (block = 0, y = 0; y < s->yb; y++) {
497 150 int block_h = s->blocks[block].h;
498 150 uint32_t *rect = dst;
499
500
2/2
✓ Branch 0 taken 1035 times.
✓ Branch 1 taken 150 times.
1185 for (x = 0; x < s->xb; x++) {
501 1035 int block_w = s->blocks[block].w;
502 1035 uint32_t *row = dst;
503
504 1035 block_h = s->blocks[block].h;
505
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 923 times.
1035 if (s->blocks[block].xor) {
506
2/2
✓ Branch 0 taken 13556 times.
✓ Branch 1 taken 112 times.
13668 for (k = 0; k < block_h; k++) {
507 13556 uint32_t *column = dst;
508
2/2
✓ Branch 0 taken 1116240 times.
✓ Branch 1 taken 13556 times.
1129796 for (l = 0; l < block_w; l++)
509 1116240 *dst++ ^= *src++;
510 13556 dst = &column[s->stride];
511 }
512 }
513 1035 dst = &row[block_w];
514 1035 ++block;
515 }
516 150 dst = &rect[block_h * s->stride];
517 }
518
519
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
520 return ret;
521
522 32 frame->key_frame = 0;
523 32 frame->pict_type = AV_PICTURE_TYPE_P;
524
525 32 ssrc = s->buffer;
526 32 ddst = frame->data[0] + (avctx->height - 1) * frame->linesize[0];
527
2/2
✓ Branch 0 taken 17462 times.
✓ Branch 1 taken 32 times.
17494 for (y = 0; y < avctx->height; y++) {
528 17462 memcpy(ddst, ssrc, avctx->width * s->bpp);
529 17462 ddst -= frame->linesize[0];
530 17462 ssrc += s->stride * 4;
531 }
532 }
533
534 34 *got_frame = 1;
535
536 34 return avpkt->size;
537 }
538
539 4 static av_cold int decode_init(AVCodecContext *avctx)
540 {
541 4 FMVCContext *s = avctx->priv_data;
542 4 int i, j, m, block = 0, h = BLOCK_HEIGHT, w = BLOCK_WIDTH;
543
544
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 switch (avctx->bits_per_coded_sample) {
545 case 16:
546 avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
547 break;
548 4 case 24:
549 4 avctx->pix_fmt = AV_PIX_FMT_BGR24;
550 4 break;
551 case 32:
552 avctx->pix_fmt = AV_PIX_FMT_BGRA;
553 break;
554 default:
555 av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n",
556 avctx->bits_per_coded_sample);
557 return AVERROR_INVALIDDATA;
558 }
559
560 4 s->stride = (avctx->width * avctx->bits_per_coded_sample + 31) / 32;
561 4 s->xb = s->stride / BLOCK_WIDTH;
562 4 m = s->stride % BLOCK_WIDTH;
563
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (m) {
564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (m < 37) {
565 w = m + BLOCK_WIDTH;
566 } else {
567 4 w = m;
568 4 s->xb++;
569 }
570 }
571
572 4 s->yb = avctx->height / BLOCK_HEIGHT;
573 4 m = avctx->height % BLOCK_HEIGHT;
574
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (m) {
575
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (m < 49) {
576 4 h = m + BLOCK_HEIGHT;
577 } else {
578 h = m;
579 s->yb++;
580 }
581 }
582
583 4 s->nb_blocks = s->xb * s->yb;
584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!s->nb_blocks)
585 return AVERROR_INVALIDDATA;
586 4 s->blocks = av_calloc(s->nb_blocks, sizeof(*s->blocks));
587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!s->blocks)
588 return AVERROR(ENOMEM);
589
590
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (i = 0; i < s->yb; i++) {
591
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 16 times.
122 for (j = 0; j < s->xb; j++) {
592
4/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 4 times.
106 if (i != (s->yb - 1) || j != (s->xb - 1)) {
593
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 80 times.
102 if (i == s->yb - 1) {
594 22 s->blocks[block].w = BLOCK_WIDTH;
595 22 s->blocks[block].h = h;
596 22 s->blocks[block].size = BLOCK_WIDTH * h;
597
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 68 times.
80 } else if (j == s->xb - 1) {
598 12 s->blocks[block].w = w;
599 12 s->blocks[block].h = BLOCK_HEIGHT;
600 12 s->blocks[block].size = BLOCK_HEIGHT * w;
601 } else {
602 68 s->blocks[block].w = BLOCK_WIDTH;
603 68 s->blocks[block].h = BLOCK_HEIGHT;
604 68 s->blocks[block].size = BLOCK_WIDTH * BLOCK_HEIGHT;
605 }
606 } else {
607 4 s->blocks[block].w = w;
608 4 s->blocks[block].h = h;
609 4 s->blocks[block].size = w * h;
610 }
611 106 block++;
612 }
613 }
614
615 4 s->bpp = avctx->bits_per_coded_sample >> 3;
616 4 s->buffer_size = avctx->width * avctx->height * 4;
617 4 s->pbuffer_size = avctx->width * avctx->height * 4;
618 4 s->buffer = av_mallocz(s->buffer_size);
619 4 s->pbuffer = av_mallocz(s->pbuffer_size);
620
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (!s->buffer || !s->pbuffer)
621 return AVERROR(ENOMEM);
622
623 4 return 0;
624 }
625
626 4 static av_cold int decode_close(AVCodecContext *avctx)
627 {
628 4 FMVCContext *s = avctx->priv_data;
629
630 4 av_freep(&s->buffer);
631 4 av_freep(&s->pbuffer);
632 4 av_freep(&s->blocks);
633
634 4 return 0;
635 }
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 };
649