FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/interplayvideo.c
Date: 2022-07-05 19:52:29
Exec Total Coverage
Lines: 453 629 72.0%
Branches: 259 366 70.8%

Line Branch Exec Source
1 /*
2 * Interplay MVE Video Decoder
3 * Copyright (C) 2003 The FFmpeg project
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 /**
23 * @file
24 * Interplay MVE Video Decoder by Mike Melanson (melanson@pcisys.net)
25 * For more information about the Interplay MVE format, visit:
26 * http://www.pcisys.net/~melanson/codecs/interplay-mve.txt
27 * This code is written in such a way that the identifiers match up
28 * with the encoding descriptions in the document.
29 *
30 * This decoder presently only supports a PAL8 output colorspace.
31 *
32 * An Interplay video frame consists of 2 parts: The decoding map and
33 * the video data. A demuxer must load these 2 parts together in a single
34 * buffer before sending it through the stream to this decoder.
35 */
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #include "libavutil/intreadwrite.h"
42
43 #define BITSTREAM_READER_LE
44 #include "avcodec.h"
45 #include "bytestream.h"
46 #include "codec_internal.h"
47 #include "decode.h"
48 #include "get_bits.h"
49 #include "hpeldsp.h"
50 #include "internal.h"
51
52 #define PALETTE_COUNT 256
53
54 typedef struct IpvideoContext {
55
56 AVCodecContext *avctx;
57 HpelDSPContext hdsp;
58 AVFrame *second_last_frame;
59 AVFrame *last_frame;
60
61 /* For format 0x10 */
62 AVFrame *cur_decode_frame;
63 AVFrame *prev_decode_frame;
64
65 const unsigned char *decoding_map;
66 int decoding_map_size;
67 const unsigned char *skip_map;
68 int skip_map_size;
69
70 int is_16bpp;
71 GetByteContext stream_ptr, mv_ptr;
72 unsigned char *pixel_ptr;
73 int line_inc;
74 int stride;
75 int upper_motion_limit_offset;
76
77 uint32_t pal[256];
78 } IpvideoContext;
79
80 341521 static int copy_from(IpvideoContext *s, AVFrame *src, AVFrame *dst, int delta_x, int delta_y)
81 {
82 341521 int width = dst->width;
83 341521 int current_offset = s->pixel_ptr - dst->data[0];
84 341521 int x = (current_offset % dst->linesize[0]) / (1 + s->is_16bpp);
85 341521 int y = current_offset / dst->linesize[0];
86 341521 int dx = delta_x + x - ((delta_x + x >= width) - (delta_x + x < 0)) * width;
87 341521 int dy = delta_y + y + (delta_x + x >= width) - (delta_x + x < 0);
88 341521 int motion_offset = dy * src->linesize[0] + dx * (1 + s->is_16bpp);
89
90
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 341521 times.
341521 if (motion_offset < 0) {
91 av_log(s->avctx, AV_LOG_ERROR, "motion offset < 0 (%d)\n", motion_offset);
92 return AVERROR_INVALIDDATA;
93
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 341521 times.
341521 } else if (motion_offset > s->upper_motion_limit_offset) {
94 av_log(s->avctx, AV_LOG_ERROR, "motion offset above limit (%d >= %d)\n",
95 motion_offset, s->upper_motion_limit_offset);
96 return AVERROR_INVALIDDATA;
97 }
98
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 341521 times.
341521 if (!src->data[0]) {
99 av_log(s->avctx, AV_LOG_ERROR, "Invalid decode type, corrupted header?\n");
100 return AVERROR(EINVAL);
101 }
102 341521 s->hdsp.put_pixels_tab[!s->is_16bpp][0](s->pixel_ptr, src->data[0] + motion_offset,
103 341521 dst->linesize[0], 8);
104 341521 return 0;
105 }
106
107 34551 static int ipvideo_decode_block_opcode_0x0(IpvideoContext *s, AVFrame *frame)
108 {
109 34551 return copy_from(s, s->last_frame, frame, 0, 0);
110 }
111
112 280419 static int ipvideo_decode_block_opcode_0x1(IpvideoContext *s, AVFrame *frame)
113 {
114 280419 return copy_from(s, s->second_last_frame, frame, 0, 0);
115 }
116
117 1282 static int ipvideo_decode_block_opcode_0x2(IpvideoContext *s, AVFrame *frame)
118 {
119 unsigned char B;
120 int x, y;
121
122 /* copy block from 2 frames ago using a motion vector; need 1 more byte */
123
2/2
✓ Branch 0 taken 579 times.
✓ Branch 1 taken 703 times.
1282 if (!s->is_16bpp) {
124 579 B = bytestream2_get_byte(&s->stream_ptr);
125 } else {
126 703 B = bytestream2_get_byte(&s->mv_ptr);
127 }
128
129
2/2
✓ Branch 0 taken 491 times.
✓ Branch 1 taken 791 times.
1282 if (B < 56) {
130 491 x = 8 + (B % 7);
131 491 y = B / 7;
132 } else {
133 791 x = -14 + ((B - 56) % 29);
134 791 y = 8 + ((B - 56) / 29);
135 }
136
137 ff_tlog(s->avctx, "motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
138 1282 return copy_from(s, s->second_last_frame, frame, x, y);
139 }
140
141 3043 static int ipvideo_decode_block_opcode_0x3(IpvideoContext *s, AVFrame *frame)
142 {
143 unsigned char B;
144 int x, y;
145
146 /* copy 8x8 block from current frame from an up/left block */
147
148 /* need 1 more byte for motion */
149
2/2
✓ Branch 0 taken 387 times.
✓ Branch 1 taken 2656 times.
3043 if (!s->is_16bpp) {
150 387 B = bytestream2_get_byte(&s->stream_ptr);
151 } else {
152 2656 B = bytestream2_get_byte(&s->mv_ptr);
153 }
154
155
2/2
✓ Branch 0 taken 1630 times.
✓ Branch 1 taken 1413 times.
3043 if (B < 56) {
156 1630 x = -(8 + (B % 7));
157 1630 y = -(B / 7);
158 } else {
159 1413 x = -(-14 + ((B - 56) % 29));
160 1413 y = -( 8 + ((B - 56) / 29));
161 }
162
163 ff_tlog(s->avctx, "motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
164 3043 return copy_from(s, frame, frame, x, y);
165 }
166
167 18863 static int ipvideo_decode_block_opcode_0x4(IpvideoContext *s, AVFrame *frame)
168 {
169 int x, y;
170 unsigned char B, BL, BH;
171
172 /* copy a block from the previous frame; need 1 more byte */
173
2/2
✓ Branch 0 taken 6043 times.
✓ Branch 1 taken 12820 times.
18863 if (!s->is_16bpp) {
174 6043 B = bytestream2_get_byte(&s->stream_ptr);
175 } else {
176 12820 B = bytestream2_get_byte(&s->mv_ptr);
177 }
178
179 18863 BL = B & 0x0F;
180 18863 BH = (B >> 4) & 0x0F;
181 18863 x = -8 + BL;
182 18863 y = -8 + BH;
183
184 ff_tlog(s->avctx, "motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
185 18863 return copy_from(s, s->last_frame, frame, x, y);
186 }
187
188 3363 static int ipvideo_decode_block_opcode_0x5(IpvideoContext *s, AVFrame *frame)
189 {
190 signed char x, y;
191
192 /* copy a block from the previous frame using an expanded range;
193 * need 2 more bytes */
194 3363 x = bytestream2_get_byte(&s->stream_ptr);
195 3363 y = bytestream2_get_byte(&s->stream_ptr);
196
197 ff_tlog(s->avctx, "motion bytes = %d, %d\n", x, y);
198 3363 return copy_from(s, s->last_frame, frame, x, y);
199 }
200
201 static int ipvideo_decode_block_opcode_0x6(IpvideoContext *s, AVFrame *frame)
202 {
203 /* mystery opcode? skip multiple blocks? */
204 av_log(s->avctx, AV_LOG_ERROR, "Help! Mystery opcode 0x6 seen\n");
205
206 /* report success */
207 return 0;
208 }
209
210 815 static int ipvideo_decode_block_opcode_0x7(IpvideoContext *s, AVFrame *frame)
211 {
212 int x, y;
213 unsigned char P[2];
214 unsigned int flags;
215
216
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 815 times.
815 if (bytestream2_get_bytes_left(&s->stream_ptr) < 4) {
217 av_log(s->avctx, AV_LOG_ERROR, "too little data for opcode 0x7\n");
218 return AVERROR_INVALIDDATA;
219 }
220
221 /* 2-color encoding */
222 815 P[0] = bytestream2_get_byte(&s->stream_ptr);
223 815 P[1] = bytestream2_get_byte(&s->stream_ptr);
224
225
2/2
✓ Branch 0 taken 719 times.
✓ Branch 1 taken 96 times.
815 if (P[0] <= P[1]) {
226
227 /* need 8 more bytes from the stream */
228
2/2
✓ Branch 0 taken 5752 times.
✓ Branch 1 taken 719 times.
6471 for (y = 0; y < 8; y++) {
229 5752 flags = bytestream2_get_byte(&s->stream_ptr) | 0x100;
230
2/2
✓ Branch 0 taken 46016 times.
✓ Branch 1 taken 5752 times.
51768 for (; flags != 1; flags >>= 1)
231 46016 *s->pixel_ptr++ = P[flags & 1];
232 5752 s->pixel_ptr += s->line_inc;
233 }
234
235 } else {
236
237 /* need 2 more bytes from the stream */
238 96 flags = bytestream2_get_le16(&s->stream_ptr);
239
2/2
✓ Branch 0 taken 384 times.
✓ Branch 1 taken 96 times.
480 for (y = 0; y < 8; y += 2) {
240
2/2
✓ Branch 0 taken 1536 times.
✓ Branch 1 taken 384 times.
1920 for (x = 0; x < 8; x += 2, flags >>= 1) {
241 1536 s->pixel_ptr[x ] =
242 1536 s->pixel_ptr[x + 1 ] =
243 1536 s->pixel_ptr[x + s->stride] =
244 1536 s->pixel_ptr[x + 1 + s->stride] = P[flags & 1];
245 }
246 384 s->pixel_ptr += s->stride * 2;
247 }
248 }
249
250 /* report success */
251 815 return 0;
252 }
253
254 1013 static int ipvideo_decode_block_opcode_0x8(IpvideoContext *s, AVFrame *frame)
255 {
256 int x, y;
257 unsigned char P[4];
258 1013 unsigned int flags = 0;
259
260
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1013 times.
1013 if (bytestream2_get_bytes_left(&s->stream_ptr) < 12) {
261 av_log(s->avctx, AV_LOG_ERROR, "too little data for opcode 0x8\n");
262 return AVERROR_INVALIDDATA;
263 }
264
265 /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on
266 * either top and bottom or left and right halves */
267 1013 P[0] = bytestream2_get_byte(&s->stream_ptr);
268 1013 P[1] = bytestream2_get_byte(&s->stream_ptr);
269
270
2/2
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 682 times.
1013 if (P[0] <= P[1]) {
271
2/2
✓ Branch 0 taken 5296 times.
✓ Branch 1 taken 331 times.
5627 for (y = 0; y < 16; y++) {
272 // new values for each 4x4 block
273
2/2
✓ Branch 0 taken 1324 times.
✓ Branch 1 taken 3972 times.
5296 if (!(y & 3)) {
274
2/2
✓ Branch 0 taken 993 times.
✓ Branch 1 taken 331 times.
1324 if (y) {
275 993 P[0] = bytestream2_get_byte(&s->stream_ptr);
276 993 P[1] = bytestream2_get_byte(&s->stream_ptr);
277 }
278 1324 flags = bytestream2_get_le16(&s->stream_ptr);
279 }
280
281
2/2
✓ Branch 0 taken 21184 times.
✓ Branch 1 taken 5296 times.
26480 for (x = 0; x < 4; x++, flags >>= 1)
282 21184 *s->pixel_ptr++ = P[flags & 1];
283 5296 s->pixel_ptr += s->stride - 4;
284 // switch to right half
285
2/2
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 4965 times.
5296 if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
286 }
287
288 } else {
289 682 flags = bytestream2_get_le32(&s->stream_ptr);
290 682 P[2] = bytestream2_get_byte(&s->stream_ptr);
291 682 P[3] = bytestream2_get_byte(&s->stream_ptr);
292
293
2/2
✓ Branch 0 taken 407 times.
✓ Branch 1 taken 275 times.
682 if (P[2] <= P[3]) {
294
295 /* vertical split; left & right halves are 2-color encoded */
296
297
2/2
✓ Branch 0 taken 6512 times.
✓ Branch 1 taken 407 times.
6919 for (y = 0; y < 16; y++) {
298
2/2
✓ Branch 0 taken 26048 times.
✓ Branch 1 taken 6512 times.
32560 for (x = 0; x < 4; x++, flags >>= 1)
299 26048 *s->pixel_ptr++ = P[flags & 1];
300 6512 s->pixel_ptr += s->stride - 4;
301 // switch to right half
302
2/2
✓ Branch 0 taken 407 times.
✓ Branch 1 taken 6105 times.
6512 if (y == 7) {
303 407 s->pixel_ptr -= 8 * s->stride - 4;
304 407 P[0] = P[2];
305 407 P[1] = P[3];
306 407 flags = bytestream2_get_le32(&s->stream_ptr);
307 }
308 }
309
310 } else {
311
312 /* horizontal split; top & bottom halves are 2-color encoded */
313
314
2/2
✓ Branch 0 taken 2200 times.
✓ Branch 1 taken 275 times.
2475 for (y = 0; y < 8; y++) {
315
2/2
✓ Branch 0 taken 275 times.
✓ Branch 1 taken 1925 times.
2200 if (y == 4) {
316 275 P[0] = P[2];
317 275 P[1] = P[3];
318 275 flags = bytestream2_get_le32(&s->stream_ptr);
319 }
320
321
2/2
✓ Branch 0 taken 17600 times.
✓ Branch 1 taken 2200 times.
19800 for (x = 0; x < 8; x++, flags >>= 1)
322 17600 *s->pixel_ptr++ = P[flags & 1];
323 2200 s->pixel_ptr += s->line_inc;
324 }
325 }
326 }
327
328 /* report success */
329 1013 return 0;
330 }
331
332 2412 static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s, AVFrame *frame)
333 {
334 int x, y;
335 unsigned char P[4];
336
337
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2412 times.
2412 if (bytestream2_get_bytes_left(&s->stream_ptr) < 8) {
338 av_log(s->avctx, AV_LOG_ERROR, "too little data for opcode 0x9\n");
339 return AVERROR_INVALIDDATA;
340 }
341
342 /* 4-color encoding */
343 2412 bytestream2_get_buffer(&s->stream_ptr, P, 4);
344
345
2/2
✓ Branch 0 taken 2053 times.
✓ Branch 1 taken 359 times.
2412 if (P[0] <= P[1]) {
346
2/2
✓ Branch 0 taken 1835 times.
✓ Branch 1 taken 218 times.
2053 if (P[2] <= P[3]) {
347
348 /* 1 of 4 colors for each pixel, need 16 more bytes */
349
2/2
✓ Branch 0 taken 14680 times.
✓ Branch 1 taken 1835 times.
16515 for (y = 0; y < 8; y++) {
350 /* get the next set of 8 2-bit flags */
351 14680 int flags = bytestream2_get_le16(&s->stream_ptr);
352
2/2
✓ Branch 0 taken 117440 times.
✓ Branch 1 taken 14680 times.
132120 for (x = 0; x < 8; x++, flags >>= 2)
353 117440 *s->pixel_ptr++ = P[flags & 0x03];
354 14680 s->pixel_ptr += s->line_inc;
355 }
356
357 } else {
358 uint32_t flags;
359
360 /* 1 of 4 colors for each 2x2 block, need 4 more bytes */
361 218 flags = bytestream2_get_le32(&s->stream_ptr);
362
363
2/2
✓ Branch 0 taken 872 times.
✓ Branch 1 taken 218 times.
1090 for (y = 0; y < 8; y += 2) {
364
2/2
✓ Branch 0 taken 3488 times.
✓ Branch 1 taken 872 times.
4360 for (x = 0; x < 8; x += 2, flags >>= 2) {
365 3488 s->pixel_ptr[x ] =
366 3488 s->pixel_ptr[x + 1 ] =
367 3488 s->pixel_ptr[x + s->stride] =
368 3488 s->pixel_ptr[x + 1 + s->stride] = P[flags & 0x03];
369 }
370 872 s->pixel_ptr += s->stride * 2;
371 }
372
373 }
374 } else {
375 uint64_t flags;
376
377 /* 1 of 4 colors for each 2x1 or 1x2 block, need 8 more bytes */
378 359 flags = bytestream2_get_le64(&s->stream_ptr);
379
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 164 times.
359 if (P[2] <= P[3]) {
380
2/2
✓ Branch 0 taken 1560 times.
✓ Branch 1 taken 195 times.
1755 for (y = 0; y < 8; y++) {
381
2/2
✓ Branch 0 taken 6240 times.
✓ Branch 1 taken 1560 times.
7800 for (x = 0; x < 8; x += 2, flags >>= 2) {
382 6240 s->pixel_ptr[x ] =
383 6240 s->pixel_ptr[x + 1] = P[flags & 0x03];
384 }
385 1560 s->pixel_ptr += s->stride;
386 }
387 } else {
388
2/2
✓ Branch 0 taken 656 times.
✓ Branch 1 taken 164 times.
820 for (y = 0; y < 8; y += 2) {
389
2/2
✓ Branch 0 taken 5248 times.
✓ Branch 1 taken 656 times.
5904 for (x = 0; x < 8; x++, flags >>= 2) {
390 5248 s->pixel_ptr[x ] =
391 5248 s->pixel_ptr[x + s->stride] = P[flags & 0x03];
392 }
393 656 s->pixel_ptr += s->stride * 2;
394 }
395 }
396 }
397
398 /* report success */
399 2412 return 0;
400 }
401
402 5451 static int ipvideo_decode_block_opcode_0xA(IpvideoContext *s, AVFrame *frame)
403 {
404 int x, y;
405 unsigned char P[8];
406 5451 int flags = 0;
407
408
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5451 times.
5451 if (bytestream2_get_bytes_left(&s->stream_ptr) < 16) {
409 av_log(s->avctx, AV_LOG_ERROR, "too little data for opcode 0xA\n");
410 return AVERROR_INVALIDDATA;
411 }
412
413 5451 bytestream2_get_buffer(&s->stream_ptr, P, 4);
414
415 /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on
416 * either top and bottom or left and right halves */
417
2/2
✓ Branch 0 taken 1907 times.
✓ Branch 1 taken 3544 times.
5451 if (P[0] <= P[1]) {
418
419 /* 4-color encoding for each quadrant; need 32 bytes */
420
2/2
✓ Branch 0 taken 30512 times.
✓ Branch 1 taken 1907 times.
32419 for (y = 0; y < 16; y++) {
421 // new values for each 4x4 block
422
2/2
✓ Branch 0 taken 7628 times.
✓ Branch 1 taken 22884 times.
30512 if (!(y & 3)) {
423
2/2
✓ Branch 0 taken 5721 times.
✓ Branch 1 taken 1907 times.
7628 if (y) bytestream2_get_buffer(&s->stream_ptr, P, 4);
424 7628 flags = bytestream2_get_le32(&s->stream_ptr);
425 }
426
427
2/2
✓ Branch 0 taken 122048 times.
✓ Branch 1 taken 30512 times.
152560 for (x = 0; x < 4; x++, flags >>= 2)
428 122048 *s->pixel_ptr++ = P[flags & 0x03];
429
430 30512 s->pixel_ptr += s->stride - 4;
431 // switch to right half
432
2/2
✓ Branch 0 taken 1907 times.
✓ Branch 1 taken 28605 times.
30512 if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
433 }
434
435 } else {
436 // vertical split?
437 int vert;
438 3544 uint64_t flags = bytestream2_get_le64(&s->stream_ptr);
439
440 3544 bytestream2_get_buffer(&s->stream_ptr, P + 4, 4);
441 3544 vert = P[4] <= P[5];
442
443 /* 4-color encoding for either left and right or top and bottom
444 * halves */
445
446
2/2
✓ Branch 0 taken 56704 times.
✓ Branch 1 taken 3544 times.
60248 for (y = 0; y < 16; y++) {
447
2/2
✓ Branch 0 taken 226816 times.
✓ Branch 1 taken 56704 times.
283520 for (x = 0; x < 4; x++, flags >>= 2)
448 226816 *s->pixel_ptr++ = P[flags & 0x03];
449
450
2/2
✓ Branch 0 taken 30576 times.
✓ Branch 1 taken 26128 times.
56704 if (vert) {
451 30576 s->pixel_ptr += s->stride - 4;
452 // switch to right half
453
2/2
✓ Branch 0 taken 1911 times.
✓ Branch 1 taken 28665 times.
30576 if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
454
2/2
✓ Branch 0 taken 13064 times.
✓ Branch 1 taken 13064 times.
26128 } else if (y & 1) s->pixel_ptr += s->line_inc;
455
456 // load values for second half
457
2/2
✓ Branch 0 taken 3544 times.
✓ Branch 1 taken 53160 times.
56704 if (y == 7) {
458 3544 memcpy(P, P + 4, 4);
459 3544 flags = bytestream2_get_le64(&s->stream_ptr);
460 }
461 }
462 }
463
464 /* report success */
465 5451 return 0;
466 }
467
468 21074 static int ipvideo_decode_block_opcode_0xB(IpvideoContext *s, AVFrame *frame)
469 {
470 int y;
471
472 /* 64-color encoding (each pixel in block is a different color) */
473
2/2
✓ Branch 0 taken 168592 times.
✓ Branch 1 taken 21074 times.
189666 for (y = 0; y < 8; y++) {
474 168592 bytestream2_get_buffer(&s->stream_ptr, s->pixel_ptr, 8);
475 168592 s->pixel_ptr += s->stride;
476 }
477
478 /* report success */
479 21074 return 0;
480 }
481
482 135 static int ipvideo_decode_block_opcode_0xC(IpvideoContext *s, AVFrame *frame)
483 {
484 int x, y;
485
486 /* 16-color block encoding: each 2x2 block is a different color */
487
2/2
✓ Branch 0 taken 540 times.
✓ Branch 1 taken 135 times.
675 for (y = 0; y < 8; y += 2) {
488
2/2
✓ Branch 0 taken 2160 times.
✓ Branch 1 taken 540 times.
2700 for (x = 0; x < 8; x += 2) {
489 2160 s->pixel_ptr[x ] =
490 2160 s->pixel_ptr[x + 1 ] =
491 2160 s->pixel_ptr[x + s->stride] =
492 2160 s->pixel_ptr[x + 1 + s->stride] = bytestream2_get_byte(&s->stream_ptr);
493 }
494 540 s->pixel_ptr += s->stride * 2;
495 }
496
497 /* report success */
498 135 return 0;
499 }
500
501 49 static int ipvideo_decode_block_opcode_0xD(IpvideoContext *s, AVFrame *frame)
502 {
503 int y;
504 unsigned char P[2];
505
506
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
49 if (bytestream2_get_bytes_left(&s->stream_ptr) < 4) {
507 av_log(s->avctx, AV_LOG_ERROR, "too little data for opcode 0xD\n");
508 return AVERROR_INVALIDDATA;
509 }
510
511 /* 4-color block encoding: each 4x4 block is a different color */
512
2/2
✓ Branch 0 taken 392 times.
✓ Branch 1 taken 49 times.
441 for (y = 0; y < 8; y++) {
513
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 294 times.
392 if (!(y & 3)) {
514 98 P[0] = bytestream2_get_byte(&s->stream_ptr);
515 98 P[1] = bytestream2_get_byte(&s->stream_ptr);
516 }
517 392 memset(s->pixel_ptr, P[0], 4);
518 392 memset(s->pixel_ptr + 4, P[1], 4);
519 392 s->pixel_ptr += s->stride;
520 }
521
522 /* report success */
523 49 return 0;
524 }
525
526 1696 static int ipvideo_decode_block_opcode_0xE(IpvideoContext *s, AVFrame *frame)
527 {
528 int y;
529 unsigned char pix;
530
531 /* 1-color encoding: the whole block is 1 solid color */
532 1696 pix = bytestream2_get_byte(&s->stream_ptr);
533
534
2/2
✓ Branch 0 taken 13568 times.
✓ Branch 1 taken 1696 times.
15264 for (y = 0; y < 8; y++) {
535 13568 memset(s->pixel_ptr, pix, 8);
536 13568 s->pixel_ptr += s->stride;
537 }
538
539 /* report success */
540 1696 return 0;
541 }
542
543 27 static int ipvideo_decode_block_opcode_0xF(IpvideoContext *s, AVFrame *frame)
544 {
545 int x, y;
546 unsigned char sample[2];
547
548 /* dithered encoding */
549 27 sample[0] = bytestream2_get_byte(&s->stream_ptr);
550 27 sample[1] = bytestream2_get_byte(&s->stream_ptr);
551
552
2/2
✓ Branch 0 taken 216 times.
✓ Branch 1 taken 27 times.
243 for (y = 0; y < 8; y++) {
553
2/2
✓ Branch 0 taken 864 times.
✓ Branch 1 taken 216 times.
1080 for (x = 0; x < 8; x += 2) {
554 864 *s->pixel_ptr++ = sample[ y & 1 ];
555 864 *s->pixel_ptr++ = sample[!(y & 1)];
556 }
557 216 s->pixel_ptr += s->line_inc;
558 }
559
560 /* report success */
561 27 return 0;
562 }
563
564 static int ipvideo_decode_block_opcode_0x6_16(IpvideoContext *s, AVFrame *frame)
565 {
566 signed char x, y;
567
568 /* copy a block from the second last frame using an expanded range */
569 x = bytestream2_get_byte(&s->stream_ptr);
570 y = bytestream2_get_byte(&s->stream_ptr);
571
572 ff_tlog(s->avctx, "motion bytes = %d, %d\n", x, y);
573 return copy_from(s, s->second_last_frame, frame, x, y);
574 }
575
576 2197 static int ipvideo_decode_block_opcode_0x7_16(IpvideoContext *s, AVFrame *frame)
577 {
578 int x, y;
579 uint16_t P[2];
580 unsigned int flags;
581 2197 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
582
583 /* 2-color encoding */
584 2197 P[0] = bytestream2_get_le16(&s->stream_ptr);
585 2197 P[1] = bytestream2_get_le16(&s->stream_ptr);
586
587
2/2
✓ Branch 0 taken 1647 times.
✓ Branch 1 taken 550 times.
2197 if (!(P[0] & 0x8000)) {
588
589
2/2
✓ Branch 0 taken 13176 times.
✓ Branch 1 taken 1647 times.
14823 for (y = 0; y < 8; y++) {
590 13176 flags = bytestream2_get_byte(&s->stream_ptr) | 0x100;
591
2/2
✓ Branch 0 taken 105408 times.
✓ Branch 1 taken 13176 times.
118584 for (; flags != 1; flags >>= 1)
592 105408 *pixel_ptr++ = P[flags & 1];
593 13176 pixel_ptr += s->line_inc;
594 }
595
596 } else {
597
598 550 flags = bytestream2_get_le16(&s->stream_ptr);
599
2/2
✓ Branch 0 taken 2200 times.
✓ Branch 1 taken 550 times.
2750 for (y = 0; y < 8; y += 2) {
600
2/2
✓ Branch 0 taken 8800 times.
✓ Branch 1 taken 2200 times.
11000 for (x = 0; x < 8; x += 2, flags >>= 1) {
601 8800 pixel_ptr[x ] =
602 8800 pixel_ptr[x + 1 ] =
603 8800 pixel_ptr[x + s->stride] =
604 8800 pixel_ptr[x + 1 + s->stride] = P[flags & 1];
605 }
606 2200 pixel_ptr += s->stride * 2;
607 }
608 }
609
610 2197 return 0;
611 }
612
613 1478 static int ipvideo_decode_block_opcode_0x8_16(IpvideoContext *s, AVFrame *frame)
614 {
615 int x, y;
616 uint16_t P[4];
617 1478 unsigned int flags = 0;
618 1478 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
619
620 /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on
621 * either top and bottom or left and right halves */
622 1478 P[0] = bytestream2_get_le16(&s->stream_ptr);
623 1478 P[1] = bytestream2_get_le16(&s->stream_ptr);
624
625
2/2
✓ Branch 0 taken 266 times.
✓ Branch 1 taken 1212 times.
1478 if (!(P[0] & 0x8000)) {
626
627
2/2
✓ Branch 0 taken 4256 times.
✓ Branch 1 taken 266 times.
4522 for (y = 0; y < 16; y++) {
628 // new values for each 4x4 block
629
2/2
✓ Branch 0 taken 1064 times.
✓ Branch 1 taken 3192 times.
4256 if (!(y & 3)) {
630
2/2
✓ Branch 0 taken 798 times.
✓ Branch 1 taken 266 times.
1064 if (y) {
631 798 P[0] = bytestream2_get_le16(&s->stream_ptr);
632 798 P[1] = bytestream2_get_le16(&s->stream_ptr);
633 }
634 1064 flags = bytestream2_get_le16(&s->stream_ptr);
635 }
636
637
2/2
✓ Branch 0 taken 17024 times.
✓ Branch 1 taken 4256 times.
21280 for (x = 0; x < 4; x++, flags >>= 1)
638 17024 *pixel_ptr++ = P[flags & 1];
639 4256 pixel_ptr += s->stride - 4;
640 // switch to right half
641
2/2
✓ Branch 0 taken 266 times.
✓ Branch 1 taken 3990 times.
4256 if (y == 7) pixel_ptr -= 8 * s->stride - 4;
642 }
643
644 } else {
645
646 1212 flags = bytestream2_get_le32(&s->stream_ptr);
647 1212 P[2] = bytestream2_get_le16(&s->stream_ptr);
648 1212 P[3] = bytestream2_get_le16(&s->stream_ptr);
649
650
2/2
✓ Branch 0 taken 402 times.
✓ Branch 1 taken 810 times.
1212 if (!(P[2] & 0x8000)) {
651
652 /* vertical split; left & right halves are 2-color encoded */
653
654
2/2
✓ Branch 0 taken 6432 times.
✓ Branch 1 taken 402 times.
6834 for (y = 0; y < 16; y++) {
655
2/2
✓ Branch 0 taken 25728 times.
✓ Branch 1 taken 6432 times.
32160 for (x = 0; x < 4; x++, flags >>= 1)
656 25728 *pixel_ptr++ = P[flags & 1];
657 6432 pixel_ptr += s->stride - 4;
658 // switch to right half
659
2/2
✓ Branch 0 taken 402 times.
✓ Branch 1 taken 6030 times.
6432 if (y == 7) {
660 402 pixel_ptr -= 8 * s->stride - 4;
661 402 P[0] = P[2];
662 402 P[1] = P[3];
663 402 flags = bytestream2_get_le32(&s->stream_ptr);
664 }
665 }
666
667 } else {
668
669 /* horizontal split; top & bottom halves are 2-color encoded */
670
671
2/2
✓ Branch 0 taken 6480 times.
✓ Branch 1 taken 810 times.
7290 for (y = 0; y < 8; y++) {
672
2/2
✓ Branch 0 taken 810 times.
✓ Branch 1 taken 5670 times.
6480 if (y == 4) {
673 810 P[0] = P[2];
674 810 P[1] = P[3];
675 810 flags = bytestream2_get_le32(&s->stream_ptr);
676 }
677
678
2/2
✓ Branch 0 taken 51840 times.
✓ Branch 1 taken 6480 times.
58320 for (x = 0; x < 8; x++, flags >>= 1)
679 51840 *pixel_ptr++ = P[flags & 1];
680 6480 pixel_ptr += s->line_inc;
681 }
682 }
683 }
684
685 /* report success */
686 1478 return 0;
687 }
688
689 6526 static int ipvideo_decode_block_opcode_0x9_16(IpvideoContext *s, AVFrame *frame)
690 {
691 int x, y;
692 uint16_t P[4];
693 6526 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
694
695 /* 4-color encoding */
696
2/2
✓ Branch 0 taken 26104 times.
✓ Branch 1 taken 6526 times.
32630 for (x = 0; x < 4; x++)
697 26104 P[x] = bytestream2_get_le16(&s->stream_ptr);
698
699
2/2
✓ Branch 0 taken 2987 times.
✓ Branch 1 taken 3539 times.
6526 if (!(P[0] & 0x8000)) {
700
2/2
✓ Branch 0 taken 2883 times.
✓ Branch 1 taken 104 times.
2987 if (!(P[2] & 0x8000)) {
701
702 /* 1 of 4 colors for each pixel */
703
2/2
✓ Branch 0 taken 23064 times.
✓ Branch 1 taken 2883 times.
25947 for (y = 0; y < 8; y++) {
704 /* get the next set of 8 2-bit flags */
705 23064 int flags = bytestream2_get_le16(&s->stream_ptr);
706
2/2
✓ Branch 0 taken 184512 times.
✓ Branch 1 taken 23064 times.
207576 for (x = 0; x < 8; x++, flags >>= 2)
707 184512 *pixel_ptr++ = P[flags & 0x03];
708 23064 pixel_ptr += s->line_inc;
709 }
710
711 } else {
712 uint32_t flags;
713
714 /* 1 of 4 colors for each 2x2 block */
715 104 flags = bytestream2_get_le32(&s->stream_ptr);
716
717
2/2
✓ Branch 0 taken 416 times.
✓ Branch 1 taken 104 times.
520 for (y = 0; y < 8; y += 2) {
718
2/2
✓ Branch 0 taken 1664 times.
✓ Branch 1 taken 416 times.
2080 for (x = 0; x < 8; x += 2, flags >>= 2) {
719 1664 pixel_ptr[x ] =
720 1664 pixel_ptr[x + 1 ] =
721 1664 pixel_ptr[x + s->stride] =
722 1664 pixel_ptr[x + 1 + s->stride] = P[flags & 0x03];
723 }
724 416 pixel_ptr += s->stride * 2;
725 }
726
727 }
728 } else {
729 uint64_t flags;
730
731 /* 1 of 4 colors for each 2x1 or 1x2 block */
732 3539 flags = bytestream2_get_le64(&s->stream_ptr);
733
2/2
✓ Branch 0 taken 2819 times.
✓ Branch 1 taken 720 times.
3539 if (!(P[2] & 0x8000)) {
734
2/2
✓ Branch 0 taken 22552 times.
✓ Branch 1 taken 2819 times.
25371 for (y = 0; y < 8; y++) {
735
2/2
✓ Branch 0 taken 90208 times.
✓ Branch 1 taken 22552 times.
112760 for (x = 0; x < 8; x += 2, flags >>= 2) {
736 90208 pixel_ptr[x ] =
737 90208 pixel_ptr[x + 1] = P[flags & 0x03];
738 }
739 22552 pixel_ptr += s->stride;
740 }
741 } else {
742
2/2
✓ Branch 0 taken 2880 times.
✓ Branch 1 taken 720 times.
3600 for (y = 0; y < 8; y += 2) {
743
2/2
✓ Branch 0 taken 23040 times.
✓ Branch 1 taken 2880 times.
25920 for (x = 0; x < 8; x++, flags >>= 2) {
744 23040 pixel_ptr[x ] =
745 23040 pixel_ptr[x + s->stride] = P[flags & 0x03];
746 }
747 2880 pixel_ptr += s->stride * 2;
748 }
749 }
750 }
751
752 /* report success */
753 6526 return 0;
754 }
755
756 7914 static int ipvideo_decode_block_opcode_0xA_16(IpvideoContext *s, AVFrame *frame)
757 {
758 int x, y;
759 uint16_t P[8];
760 7914 int flags = 0;
761 7914 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
762
763
2/2
✓ Branch 0 taken 31656 times.
✓ Branch 1 taken 7914 times.
39570 for (x = 0; x < 4; x++)
764 31656 P[x] = bytestream2_get_le16(&s->stream_ptr);
765
766 /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on
767 * either top and bottom or left and right halves */
768
2/2
✓ Branch 0 taken 3090 times.
✓ Branch 1 taken 4824 times.
7914 if (!(P[0] & 0x8000)) {
769
770 /* 4-color encoding for each quadrant */
771
2/2
✓ Branch 0 taken 49440 times.
✓ Branch 1 taken 3090 times.
52530 for (y = 0; y < 16; y++) {
772 // new values for each 4x4 block
773
2/2
✓ Branch 0 taken 12360 times.
✓ Branch 1 taken 37080 times.
49440 if (!(y & 3)) {
774
2/2
✓ Branch 0 taken 9270 times.
✓ Branch 1 taken 3090 times.
12360 if (y)
775
2/2
✓ Branch 0 taken 37080 times.
✓ Branch 1 taken 9270 times.
46350 for (x = 0; x < 4; x++)
776 37080 P[x] = bytestream2_get_le16(&s->stream_ptr);
777 12360 flags = bytestream2_get_le32(&s->stream_ptr);
778 }
779
780
2/2
✓ Branch 0 taken 197760 times.
✓ Branch 1 taken 49440 times.
247200 for (x = 0; x < 4; x++, flags >>= 2)
781 197760 *pixel_ptr++ = P[flags & 0x03];
782
783 49440 pixel_ptr += s->stride - 4;
784 // switch to right half
785
2/2
✓ Branch 0 taken 3090 times.
✓ Branch 1 taken 46350 times.
49440 if (y == 7) pixel_ptr -= 8 * s->stride - 4;
786 }
787
788 } else {
789 // vertical split?
790 int vert;
791 4824 uint64_t flags = bytestream2_get_le64(&s->stream_ptr);
792
793
2/2
✓ Branch 0 taken 19296 times.
✓ Branch 1 taken 4824 times.
24120 for (x = 4; x < 8; x++)
794 19296 P[x] = bytestream2_get_le16(&s->stream_ptr);
795 4824 vert = !(P[4] & 0x8000);
796
797 /* 4-color encoding for either left and right or top and bottom
798 * halves */
799
800
2/2
✓ Branch 0 taken 77184 times.
✓ Branch 1 taken 4824 times.
82008 for (y = 0; y < 16; y++) {
801
2/2
✓ Branch 0 taken 308736 times.
✓ Branch 1 taken 77184 times.
385920 for (x = 0; x < 4; x++, flags >>= 2)
802 308736 *pixel_ptr++ = P[flags & 0x03];
803
804
2/2
✓ Branch 0 taken 26000 times.
✓ Branch 1 taken 51184 times.
77184 if (vert) {
805 26000 pixel_ptr += s->stride - 4;
806 // switch to right half
807
2/2
✓ Branch 0 taken 1625 times.
✓ Branch 1 taken 24375 times.
26000 if (y == 7) pixel_ptr -= 8 * s->stride - 4;
808
2/2
✓ Branch 0 taken 25592 times.
✓ Branch 1 taken 25592 times.
51184 } else if (y & 1) pixel_ptr += s->line_inc;
809
810 // load values for second half
811
2/2
✓ Branch 0 taken 4824 times.
✓ Branch 1 taken 72360 times.
77184 if (y == 7) {
812 4824 memcpy(P, P + 4, 8);
813 4824 flags = bytestream2_get_le64(&s->stream_ptr);
814 }
815 }
816 }
817
818 /* report success */
819 7914 return 0;
820 }
821
822 1690 static int ipvideo_decode_block_opcode_0xB_16(IpvideoContext *s, AVFrame *frame)
823 {
824 int x, y;
825 1690 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
826
827 /* 64-color encoding (each pixel in block is a different color) */
828
2/2
✓ Branch 0 taken 13520 times.
✓ Branch 1 taken 1690 times.
15210 for (y = 0; y < 8; y++) {
829
2/2
✓ Branch 0 taken 108160 times.
✓ Branch 1 taken 13520 times.
121680 for (x = 0; x < 8; x++)
830 108160 pixel_ptr[x] = bytestream2_get_le16(&s->stream_ptr);
831 13520 pixel_ptr += s->stride;
832 }
833
834 /* report success */
835 1690 return 0;
836 }
837
838 8 static int ipvideo_decode_block_opcode_0xC_16(IpvideoContext *s, AVFrame *frame)
839 {
840 int x, y;
841 8 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
842
843 /* 16-color block encoding: each 2x2 block is a different color */
844
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 8 times.
40 for (y = 0; y < 8; y += 2) {
845
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 32 times.
160 for (x = 0; x < 8; x += 2) {
846 128 pixel_ptr[x ] =
847 128 pixel_ptr[x + 1 ] =
848 128 pixel_ptr[x + s->stride] =
849 128 pixel_ptr[x + 1 + s->stride] = bytestream2_get_le16(&s->stream_ptr);
850 }
851 32 pixel_ptr += s->stride * 2;
852 }
853
854 /* report success */
855 8 return 0;
856 }
857
858 38 static int ipvideo_decode_block_opcode_0xD_16(IpvideoContext *s, AVFrame *frame)
859 {
860 int x, y;
861 uint16_t P[2];
862 38 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
863
864 /* 4-color block encoding: each 4x4 block is a different color */
865
2/2
✓ Branch 0 taken 304 times.
✓ Branch 1 taken 38 times.
342 for (y = 0; y < 8; y++) {
866
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 228 times.
304 if (!(y & 3)) {
867 76 P[0] = bytestream2_get_le16(&s->stream_ptr);
868 76 P[1] = bytestream2_get_le16(&s->stream_ptr);
869 }
870
2/2
✓ Branch 0 taken 2432 times.
✓ Branch 1 taken 304 times.
2736 for (x = 0; x < 8; x++)
871 2432 pixel_ptr[x] = P[x >> 2];
872 304 pixel_ptr += s->stride;
873 }
874
875 /* report success */
876 38 return 0;
877 }
878
879 3556 static int ipvideo_decode_block_opcode_0xE_16(IpvideoContext *s, AVFrame *frame)
880 {
881 int x, y;
882 uint16_t pix;
883 3556 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
884
885 /* 1-color encoding: the whole block is 1 solid color */
886 3556 pix = bytestream2_get_le16(&s->stream_ptr);
887
888
2/2
✓ Branch 0 taken 28448 times.
✓ Branch 1 taken 3556 times.
32004 for (y = 0; y < 8; y++) {
889
2/2
✓ Branch 0 taken 227584 times.
✓ Branch 1 taken 28448 times.
256032 for (x = 0; x < 8; x++)
890 227584 pixel_ptr[x] = pix;
891 28448 pixel_ptr += s->stride;
892 }
893
894 /* report success */
895 3556 return 0;
896 }
897
898 static int (* const ipvideo_decode_block[])(IpvideoContext *s, AVFrame *frame) = {
899 ipvideo_decode_block_opcode_0x0, ipvideo_decode_block_opcode_0x1,
900 ipvideo_decode_block_opcode_0x2, ipvideo_decode_block_opcode_0x3,
901 ipvideo_decode_block_opcode_0x4, ipvideo_decode_block_opcode_0x5,
902 ipvideo_decode_block_opcode_0x6, ipvideo_decode_block_opcode_0x7,
903 ipvideo_decode_block_opcode_0x8, ipvideo_decode_block_opcode_0x9,
904 ipvideo_decode_block_opcode_0xA, ipvideo_decode_block_opcode_0xB,
905 ipvideo_decode_block_opcode_0xC, ipvideo_decode_block_opcode_0xD,
906 ipvideo_decode_block_opcode_0xE, ipvideo_decode_block_opcode_0xF,
907 };
908
909 static int (* const ipvideo_decode_block16[])(IpvideoContext *s, AVFrame *frame) = {
910 ipvideo_decode_block_opcode_0x0, ipvideo_decode_block_opcode_0x1,
911 ipvideo_decode_block_opcode_0x2, ipvideo_decode_block_opcode_0x3,
912 ipvideo_decode_block_opcode_0x4, ipvideo_decode_block_opcode_0x5,
913 ipvideo_decode_block_opcode_0x6_16, ipvideo_decode_block_opcode_0x7_16,
914 ipvideo_decode_block_opcode_0x8_16, ipvideo_decode_block_opcode_0x9_16,
915 ipvideo_decode_block_opcode_0xA_16, ipvideo_decode_block_opcode_0xB_16,
916 ipvideo_decode_block_opcode_0xC_16, ipvideo_decode_block_opcode_0xD_16,
917 ipvideo_decode_block_opcode_0xE_16, ipvideo_decode_block_opcode_0x1,
918 };
919
920 static void ipvideo_format_06_firstpass(IpvideoContext *s, AVFrame *frame, int16_t opcode)
921 {
922 int line;
923
924 if (!opcode) {
925 for (line = 0; line < 8; ++line) {
926 bytestream2_get_buffer(&s->stream_ptr, s->pixel_ptr, 8);
927 s->pixel_ptr += s->stride;
928 }
929 } else {
930 /* Don't try to copy second_last_frame data on the first frames */
931 if (s->avctx->frame_number > 2)
932 copy_from(s, s->second_last_frame, frame, 0, 0);
933 }
934 }
935
936 static void ipvideo_format_06_secondpass(IpvideoContext *s, AVFrame *frame, int16_t opcode)
937 {
938 int off_x, off_y;
939
940 if (opcode < 0) {
941 off_x = ((uint16_t)opcode - 0xC000) % frame->width;
942 off_y = ((uint16_t)opcode - 0xC000) / frame->width;
943 copy_from(s, s->last_frame, frame, off_x, off_y);
944 } else if (opcode > 0) {
945 off_x = ((uint16_t)opcode - 0x4000) % frame->width;
946 off_y = ((uint16_t)opcode - 0x4000) / frame->width;
947 copy_from(s, frame, frame, off_x, off_y);
948 }
949 }
950
951 static void (* const ipvideo_format_06_passes[])(IpvideoContext *s, AVFrame *frame, int16_t op) = {
952 ipvideo_format_06_firstpass, ipvideo_format_06_secondpass,
953 };
954
955 static void ipvideo_decode_format_06_opcodes(IpvideoContext *s, AVFrame *frame)
956 {
957 int pass, x, y;
958 int16_t opcode;
959 GetByteContext decoding_map_ptr;
960
961 /* this is PAL8, so make the palette available */
962 memcpy(frame->data[1], s->pal, AVPALETTE_SIZE);
963 s->stride = frame->linesize[0];
964
965 s->line_inc = s->stride - 8;
966 s->upper_motion_limit_offset = (s->avctx->height - 8) * frame->linesize[0]
967 + (s->avctx->width - 8) * (1 + s->is_16bpp);
968
969 bytestream2_init(&decoding_map_ptr, s->decoding_map, s->decoding_map_size);
970
971 for (pass = 0; pass < 2; ++pass) {
972 bytestream2_seek(&decoding_map_ptr, 0, SEEK_SET);
973 for (y = 0; y < s->avctx->height; y += 8) {
974 for (x = 0; x < s->avctx->width; x += 8) {
975 opcode = bytestream2_get_le16(&decoding_map_ptr);
976
977 ff_tlog(s->avctx,
978 " block @ (%3d, %3d): opcode 0x%X, data ptr offset %d\n",
979 x, y, opcode, bytestream2_tell(&s->stream_ptr));
980
981 s->pixel_ptr = frame->data[0] + x + y * frame->linesize[0];
982 ipvideo_format_06_passes[pass](s, frame, opcode);
983 }
984 }
985 }
986
987 if (bytestream2_get_bytes_left(&s->stream_ptr) > 1) {
988 av_log(s->avctx, AV_LOG_DEBUG,
989 "decode finished with %d bytes left over\n",
990 bytestream2_get_bytes_left(&s->stream_ptr));
991 }
992 }
993
994 static void ipvideo_format_10_firstpass(IpvideoContext *s, AVFrame *frame, int16_t opcode)
995 {
996 int line;
997
998 if (!opcode) {
999 for (line = 0; line < 8; ++line) {
1000 bytestream2_get_buffer(&s->stream_ptr, s->pixel_ptr, 8);
1001 s->pixel_ptr += s->stride;
1002 }
1003 }
1004 }
1005
1006 static void ipvideo_format_10_secondpass(IpvideoContext *s, AVFrame *frame, int16_t opcode)
1007 {
1008 int off_x, off_y;
1009
1010 if (opcode < 0) {
1011 off_x = ((uint16_t)opcode - 0xC000) % s->cur_decode_frame->width;
1012 off_y = ((uint16_t)opcode - 0xC000) / s->cur_decode_frame->width;
1013 copy_from(s, s->prev_decode_frame, s->cur_decode_frame, off_x, off_y);
1014 } else if (opcode > 0) {
1015 off_x = ((uint16_t)opcode - 0x4000) % s->cur_decode_frame->width;
1016 off_y = ((uint16_t)opcode - 0x4000) / s->cur_decode_frame->width;
1017 copy_from(s, s->cur_decode_frame, s->cur_decode_frame, off_x, off_y);
1018 }
1019 }
1020
1021 static void (* const ipvideo_format_10_passes[])(IpvideoContext *s, AVFrame *frame, int16_t op) = {
1022 ipvideo_format_10_firstpass, ipvideo_format_10_secondpass,
1023 };
1024
1025 static void ipvideo_decode_format_10_opcodes(IpvideoContext *s, AVFrame *frame)
1026 {
1027 int pass, x, y, changed_block;
1028 int16_t opcode, skip;
1029 GetByteContext decoding_map_ptr;
1030 GetByteContext skip_map_ptr;
1031
1032 bytestream2_skip(&s->stream_ptr, 14); /* data starts 14 bytes in */
1033
1034 /* this is PAL8, so make the palette available */
1035 memcpy(frame->data[1], s->pal, AVPALETTE_SIZE);
1036 s->stride = frame->linesize[0];
1037
1038 s->line_inc = s->stride - 8;
1039 s->upper_motion_limit_offset = (s->avctx->height - 8) * frame->linesize[0]
1040 + (s->avctx->width - 8) * (1 + s->is_16bpp);
1041
1042 bytestream2_init(&decoding_map_ptr, s->decoding_map, s->decoding_map_size);
1043 bytestream2_init(&skip_map_ptr, s->skip_map, s->skip_map_size);
1044
1045 for (pass = 0; pass < 2; ++pass) {
1046 bytestream2_seek(&decoding_map_ptr, 0, SEEK_SET);
1047 bytestream2_seek(&skip_map_ptr, 0, SEEK_SET);
1048 skip = bytestream2_get_le16(&skip_map_ptr);
1049
1050 for (y = 0; y < s->avctx->height; y += 8) {
1051 for (x = 0; x < s->avctx->width; x += 8) {
1052 s->pixel_ptr = s->cur_decode_frame->data[0] + x + y * s->cur_decode_frame->linesize[0];
1053
1054 while (skip <= 0) {
1055 if (skip != -0x8000 && skip) {
1056 opcode = bytestream2_get_le16(&decoding_map_ptr);
1057 ipvideo_format_10_passes[pass](s, frame, opcode);
1058 break;
1059 }
1060 if (bytestream2_get_bytes_left(&skip_map_ptr) < 2)
1061 return;
1062 skip = bytestream2_get_le16(&skip_map_ptr);
1063 }
1064 skip *= 2;
1065 }
1066 }
1067 }
1068
1069 bytestream2_seek(&skip_map_ptr, 0, SEEK_SET);
1070 skip = bytestream2_get_le16(&skip_map_ptr);
1071 for (y = 0; y < s->avctx->height; y += 8) {
1072 for (x = 0; x < s->avctx->width; x += 8) {
1073 changed_block = 0;
1074 s->pixel_ptr = frame->data[0] + x + y*frame->linesize[0];
1075
1076 while (skip <= 0) {
1077 if (skip != -0x8000 && skip) {
1078 changed_block = 1;
1079 break;
1080 }
1081 if (bytestream2_get_bytes_left(&skip_map_ptr) < 2)
1082 return;
1083 skip = bytestream2_get_le16(&skip_map_ptr);
1084 }
1085
1086 if (changed_block) {
1087 copy_from(s, s->cur_decode_frame, frame, 0, 0);
1088 } else {
1089 /* Don't try to copy last_frame data on the first frame */
1090 if (s->avctx->frame_number)
1091 copy_from(s, s->last_frame, frame, 0, 0);
1092 }
1093 skip *= 2;
1094 }
1095 }
1096
1097 FFSWAP(AVFrame*, s->prev_decode_frame, s->cur_decode_frame);
1098
1099 if (bytestream2_get_bytes_left(&s->stream_ptr) > 1) {
1100 av_log(s->avctx, AV_LOG_DEBUG,
1101 "decode finished with %d bytes left over\n",
1102 bytestream2_get_bytes_left(&s->stream_ptr));
1103 }
1104 }
1105
1106 160 static void ipvideo_decode_format_11_opcodes(IpvideoContext *s, AVFrame *frame)
1107 {
1108 int x, y;
1109 unsigned char opcode;
1110 int ret;
1111 GetBitContext gb;
1112
1113 160 bytestream2_skip(&s->stream_ptr, 14); /* data starts 14 bytes in */
1114
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 50 times.
160 if (!s->is_16bpp) {
1115 /* this is PAL8, so make the palette available */
1116 110 memcpy(frame->data[1], s->pal, AVPALETTE_SIZE);
1117
1118 110 s->stride = frame->linesize[0];
1119 } else {
1120 50 s->stride = frame->linesize[0] >> 1;
1121 50 s->mv_ptr = s->stream_ptr;
1122 50 bytestream2_skip(&s->mv_ptr, bytestream2_get_le16(&s->stream_ptr));
1123 }
1124 160 s->line_inc = s->stride - 8;
1125 160 s->upper_motion_limit_offset = (s->avctx->height - 8) * frame->linesize[0]
1126 160 + (s->avctx->width - 8) * (1 + s->is_16bpp);
1127
1128 160 init_get_bits(&gb, s->decoding_map, s->decoding_map_size * 8);
1129
2/2
✓ Branch 0 taken 6400 times.
✓ Branch 1 taken 160 times.
6560 for (y = 0; y < s->avctx->height; y += 8) {
1130
2/2
✓ Branch 0 taken 397600 times.
✓ Branch 1 taken 6400 times.
404000 for (x = 0; x < s->avctx->width; x += 8) {
1131
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 397600 times.
397600 if (get_bits_left(&gb) < 4)
1132 return;
1133 397600 opcode = get_bits(&gb, 4);
1134
1135 ff_tlog(s->avctx,
1136 " block @ (%3d, %3d): encoding 0x%X, data ptr offset %d\n",
1137 x, y, opcode, bytestream2_tell(&s->stream_ptr));
1138
1139
2/2
✓ Branch 0 taken 237600 times.
✓ Branch 1 taken 160000 times.
397600 if (!s->is_16bpp) {
1140 237600 s->pixel_ptr = frame->data[0] + x
1141 237600 + y*frame->linesize[0];
1142 237600 ret = ipvideo_decode_block[opcode](s, frame);
1143 } else {
1144 160000 s->pixel_ptr = frame->data[0] + x*2
1145 160000 + y*frame->linesize[0];
1146 160000 ret = ipvideo_decode_block16[opcode](s, frame);
1147 }
1148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 397600 times.
397600 if (ret != 0) {
1149 av_log(s->avctx, AV_LOG_ERROR, "decode problem on frame %d, @ block (%d, %d)\n",
1150 s->avctx->frame_number, x, y);
1151 return;
1152 }
1153 }
1154 }
1155
2/2
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 112 times.
160 if (bytestream2_get_bytes_left(&s->stream_ptr) > 1) {
1156 48 av_log(s->avctx, AV_LOG_DEBUG,
1157 "decode finished with %d bytes left over\n",
1158 bytestream2_get_bytes_left(&s->stream_ptr));
1159 }
1160 }
1161
1162 5 static av_cold int ipvideo_decode_init(AVCodecContext *avctx)
1163 {
1164 5 IpvideoContext *s = avctx->priv_data;
1165
1166 5 s->avctx = avctx;
1167
1168 5 s->is_16bpp = avctx->bits_per_coded_sample == 16;
1169
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 avctx->pix_fmt = s->is_16bpp ? AV_PIX_FMT_RGB555 : AV_PIX_FMT_PAL8;
1170
1171 5 ff_hpeldsp_init(&s->hdsp, avctx->flags);
1172
1173 5 s->last_frame = av_frame_alloc();
1174 5 s->second_last_frame = av_frame_alloc();
1175 5 s->cur_decode_frame = av_frame_alloc();
1176 5 s->prev_decode_frame = av_frame_alloc();
1177
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 if (!s->last_frame || !s->second_last_frame ||
1178
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 !s->cur_decode_frame || !s->prev_decode_frame) {
1179 return AVERROR(ENOMEM);
1180 }
1181
1182 5 s->cur_decode_frame->width = avctx->width;
1183 5 s->prev_decode_frame->width = avctx->width;
1184 5 s->cur_decode_frame->height = avctx->height;
1185 5 s->prev_decode_frame->height = avctx->height;
1186 5 s->cur_decode_frame->format = avctx->pix_fmt;
1187 5 s->prev_decode_frame->format = avctx->pix_fmt;
1188
1189 5 return 0;
1190 }
1191
1192 160 static int ipvideo_decode_frame(AVCodecContext *avctx, AVFrame *frame,
1193 int *got_frame, AVPacket *avpkt)
1194 {
1195 160 const uint8_t *buf = avpkt->data;
1196 160 int buf_size = avpkt->size;
1197 160 IpvideoContext *s = avctx->priv_data;
1198 int ret;
1199 int send_buffer;
1200 int frame_format;
1201 int video_data_size;
1202
1203
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 158 times.
160 if (av_packet_get_side_data(avpkt, AV_PKT_DATA_PARAM_CHANGE, NULL)) {
1204 2 av_frame_unref(s->last_frame);
1205 2 av_frame_unref(s->second_last_frame);
1206 2 av_frame_unref(s->cur_decode_frame);
1207 2 av_frame_unref(s->prev_decode_frame);
1208 }
1209
1210
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 158 times.
160 if (!s->cur_decode_frame->data[0]) {
1211 2 ret = ff_get_buffer(avctx, s->cur_decode_frame, 0);
1212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
1213 return ret;
1214
1215 2 ret = ff_get_buffer(avctx, s->prev_decode_frame, 0);
1216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0) {
1217 av_frame_unref(s->cur_decode_frame);
1218 return ret;
1219 }
1220 }
1221
1222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 if (buf_size < 8)
1223 return AVERROR_INVALIDDATA;
1224
1225 160 frame_format = AV_RL8(buf);
1226 160 send_buffer = AV_RL8(buf + 1);
1227 160 video_data_size = AV_RL16(buf + 2);
1228 160 s->decoding_map_size = AV_RL16(buf + 4);
1229 160 s->skip_map_size = AV_RL16(buf + 6);
1230
1231
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 160 times.
✗ Branch 3 not taken.
160 switch (frame_format) {
1232 case 0x06:
1233 if (s->decoding_map_size) {
1234 av_log(avctx, AV_LOG_ERROR, "Decoding map for format 0x06\n");
1235 return AVERROR_INVALIDDATA;
1236 }
1237
1238 if (s->skip_map_size) {
1239 av_log(avctx, AV_LOG_ERROR, "Skip map for format 0x06\n");
1240 return AVERROR_INVALIDDATA;
1241 }
1242
1243 if (s->is_16bpp) {
1244 av_log(avctx, AV_LOG_ERROR, "Video format 0x06 does not support 16bpp movies\n");
1245 return AVERROR_INVALIDDATA;
1246 }
1247
1248 /* Decoding map for 0x06 frame format is at the top of pixeldata */
1249 s->decoding_map_size = ((s->avctx->width / 8) * (s->avctx->height / 8)) * 2;
1250 s->decoding_map = buf + 8 + 14; /* 14 bits of op data */
1251 video_data_size -= s->decoding_map_size + 14;
1252 if (video_data_size <= 0 || s->decoding_map_size == 0)
1253 return AVERROR_INVALIDDATA;
1254
1255 if (buf_size < 8 + s->decoding_map_size + 14 + video_data_size)
1256 return AVERROR_INVALIDDATA;
1257
1258 bytestream2_init(&s->stream_ptr, buf + 8 + s->decoding_map_size + 14, video_data_size);
1259
1260 break;
1261
1262 case 0x10:
1263 if (! s->decoding_map_size) {
1264 av_log(avctx, AV_LOG_ERROR, "Empty decoding map for format 0x10\n");
1265 return AVERROR_INVALIDDATA;
1266 }
1267
1268 if (! s->skip_map_size) {
1269 av_log(avctx, AV_LOG_ERROR, "Empty skip map for format 0x10\n");
1270 return AVERROR_INVALIDDATA;
1271 }
1272
1273 if (s->is_16bpp) {
1274 av_log(avctx, AV_LOG_ERROR, "Video format 0x10 does not support 16bpp movies\n");
1275 return AVERROR_INVALIDDATA;
1276 }
1277
1278 if (buf_size < 8 + video_data_size + s->decoding_map_size + s->skip_map_size)
1279 return AVERROR_INVALIDDATA;
1280
1281 bytestream2_init(&s->stream_ptr, buf + 8, video_data_size);
1282 s->decoding_map = buf + 8 + video_data_size;
1283 s->skip_map = buf + 8 + video_data_size + s->decoding_map_size;
1284
1285 break;
1286
1287 160 case 0x11:
1288
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 if (! s->decoding_map_size) {
1289 av_log(avctx, AV_LOG_ERROR, "Empty decoding map for format 0x11\n");
1290 return AVERROR_INVALIDDATA;
1291 }
1292
1293
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 if (s->skip_map_size) {
1294 av_log(avctx, AV_LOG_ERROR, "Skip map for format 0x11\n");
1295 return AVERROR_INVALIDDATA;
1296 }
1297
1298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 if (buf_size < 8 + video_data_size + s->decoding_map_size)
1299 return AVERROR_INVALIDDATA;
1300
1301 160 bytestream2_init(&s->stream_ptr, buf + 8, video_data_size);
1302 160 s->decoding_map = buf + 8 + video_data_size;
1303
1304 160 break;
1305
1306 default:
1307 av_log(avctx, AV_LOG_ERROR, "Frame type 0x%02X unsupported\n", frame_format);
1308 }
1309
1310 /* ensure we can't overread the packet */
1311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 if (buf_size < 8 + s->decoding_map_size + video_data_size + s->skip_map_size) {
1312 av_log(avctx, AV_LOG_ERROR, "Invalid IP packet size\n");
1313 return AVERROR_INVALIDDATA;
1314 }
1315
1316
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 160 times.
160 if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
1317 return ret;
1318
1319
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 50 times.
160 if (!s->is_16bpp) {
1320 110 frame->palette_has_changed = ff_copy_palette(s->pal, avpkt, avctx);
1321 }
1322
1323
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 160 times.
✗ Branch 3 not taken.
160 switch (frame_format) {
1324 case 0x06:
1325 ipvideo_decode_format_06_opcodes(s, frame);
1326 break;
1327 case 0x10:
1328 ipvideo_decode_format_10_opcodes(s, frame);
1329 break;
1330 160 case 0x11:
1331 160 ipvideo_decode_format_11_opcodes(s, frame);
1332 160 break;
1333 }
1334
1335 160 *got_frame = send_buffer;
1336
1337 /* shuffle frames */
1338 160 av_frame_unref(s->second_last_frame);
1339 160 FFSWAP(AVFrame*, s->second_last_frame, s->last_frame);
1340
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 160 times.
160 if ((ret = av_frame_ref(s->last_frame, frame)) < 0)
1341 return ret;
1342
1343 /* report that the buffer was completely consumed */
1344 160 return buf_size;
1345 }
1346
1347 5 static av_cold int ipvideo_decode_end(AVCodecContext *avctx)
1348 {
1349 5 IpvideoContext *s = avctx->priv_data;
1350
1351 5 av_frame_free(&s->last_frame);
1352 5 av_frame_free(&s->second_last_frame);
1353 5 av_frame_free(&s->cur_decode_frame);
1354 5 av_frame_free(&s->prev_decode_frame);
1355
1356 5 return 0;
1357 }
1358
1359 const FFCodec ff_interplay_video_decoder = {
1360 .p.name = "interplayvideo",
1361 .p.long_name = NULL_IF_CONFIG_SMALL("Interplay MVE video"),
1362 .p.type = AVMEDIA_TYPE_VIDEO,
1363 .p.id = AV_CODEC_ID_INTERPLAY_VIDEO,
1364 .priv_data_size = sizeof(IpvideoContext),
1365 .init = ipvideo_decode_init,
1366 .close = ipvideo_decode_end,
1367 FF_CODEC_DECODE_CB(ipvideo_decode_frame),
1368 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_PARAM_CHANGE,
1369 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
1370 };
1371