FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/imm4.c
Date: 2025-10-10 03:51:19
Exec Total Coverage
Lines: 0 281 0.0%
Functions: 0 10 0.0%
Branches: 0 119 0.0%

Line Branch Exec Source
1 /*
2 * Infinity IMM4 decoder
3 *
4 * Copyright (c) 2018 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 <stddef.h>
24 #include <string.h>
25
26 #include "libavutil/attributes.h"
27 #include "libavutil/mem.h"
28 #include "libavutil/mem_internal.h"
29 #include "libavutil/thread.h"
30
31 #include "avcodec.h"
32 #include "bswapdsp.h"
33 #include "codec_internal.h"
34 #include "decode.h"
35 #include "copy_block.h"
36 #include "get_bits.h"
37 #include "idctdsp.h"
38
39 #define CBPLO_VLC_BITS 6
40 #define CBPHI_VLC_BITS 6
41 #define BLKTYPE_VLC_BITS 9
42 #define BLOCK_VLC_BITS 12
43
44 typedef struct IMM4Context {
45 BswapDSPContext bdsp;
46 GetBitContext gb;
47
48 AVFrame *prev_frame;
49 uint8_t *bitstream;
50 int bitstream_size;
51
52 int factor;
53 unsigned lo;
54 unsigned hi;
55
56 IDCTDSPContext idsp;
57 DECLARE_ALIGNED(32, int16_t, block)[6][64];
58 } IMM4Context;
59
60 static const uint8_t intra_cb[] = {
61 24, 18, 12
62 };
63
64 static const uint8_t inter_cb[] = {
65 30, 20, 15
66 };
67
68 static const uint8_t cbplo[][2] = {
69 { 0,-6 }, { 0x01, 6 }, { 0x02, 6 }, { 0x03, 6 }, { 0x00, 4 },
70 { 0x01, 3 }, { 0x02, 3 }, { 0x03, 3 }, { 0x00, 1 },
71 };
72
73 static const uint8_t cbphi_bits[] = {
74 4, 5, 5, 4, 5, 4, 6, 4, 5, 6, 4, 4, 4, 4, 4, 2
75 };
76
77 static const uint8_t cbphi_codes[] = {
78 3, 5, 4, 9, 3, 7, 2, 11, 2, 3, 5, 10, 4, 8, 6, 3
79 };
80
81 static const uint8_t blktype[][2] = {
82 { 0,-8 }, { 0x34, 9 }, { 0,-9 }, { 0x14, 9 }, { 0,-9 },
83 { 0x23, 8 }, { 0x13, 8 }, { 0x32, 8 }, { 0x33, 7 }, { 0x22, 7 },
84 { 0x12, 7 }, { 0x21, 7 }, { 0x11, 7 }, { 0x04, 6 }, { 0x30, 6 },
85 { 0x03, 5 }, { 0x20, 4 }, { 0x10, 4 }, { 0x02, 3 }, { 0x01, 3 },
86 { 0x00, 1 },
87 };
88
89 static const uint16_t block_symbols[] = {
90 0, 0x4082, 0x4003, 0x000B, 0x000A, 0x4E01, 0x4D81, 0x4D01, 0x4C81,
91 0x0482, 0x0402, 0x0382, 0x0302, 0x0282, 0x0183, 0x0103, 0x0084, 0x000C,
92 0x0085, 0x0B81, 0x0C01, 0x4E81, 0x4F01, 0x4F81, 0x5001, 0x0086, 0x0104,
93 0x0203, 0x0283, 0x0303, 0x0502, 0x0C81, 0x0D01, 0x5081, 0x5101, 0x5181,
94 0x5201, 0x5281, 0x5301, 0x5381, 0x5401, 0x0000, 0x0009, 0x0008, 0x4C01,
95 0x4B81, 0x4B01, 0x4A81, 0x4A01, 0x4981, 0x4901, 0x4881, 0x4002, 0x0B01,
96 0x0A81, 0x0A01, 0x0981, 0x0901, 0x0881, 0x0801, 0x0781, 0x0202, 0x0182,
97 0x0007, 0x0006, 0x4801, 0x4781, 0x4701, 0x4681, 0x4601, 0x4581, 0x4501,
98 0x4481, 0x0701, 0x0681, 0x0102, 0x0083, 0x0005, 0x4401, 0x4381, 0x4301,
99 0x4281, 0x0601, 0x0581, 0x0501, 0x0004, 0x4201, 0x4181, 0x4101, 0x4081,
100 0x0481, 0x0401, 0x0381, 0x0301, 0x0082, 0x0003, 0x0281, 0x0201, 0x0181,
101 0x4001, 0x0001, 0x0081, 0x0101, 0x0002,
102 };
103
104 static const uint8_t block_bits[] = {
105 -9, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11,
106 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
107 12, 12, 12, 7, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
108 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
109 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6,
110 6, 5, 5, 5, 4, 2, 3, 4, 4,
111 };
112
113 static VLCElem cbplo_tab[1 << CBPLO_VLC_BITS];
114 static VLCElem cbphi_tab[1 << CBPHI_VLC_BITS];
115 static VLCElem blktype_tab[1 << BLKTYPE_VLC_BITS];
116 static VLCElem block_tab[1 << BLOCK_VLC_BITS];
117
118 static int get_cbphi(GetBitContext *gb, int x)
119 {
120 int value;
121
122 value = get_vlc2(gb, cbphi_tab, CBPHI_VLC_BITS, 1);
123 if (value < 0)
124 return AVERROR_INVALIDDATA;
125
126 return x ? value : 15 - value;
127 }
128
129 static int decode_block(AVCodecContext *avctx, GetBitContext *gb,
130 int block, int factor, int flag, int offset, int flag2)
131 {
132 IMM4Context *s = avctx->priv_data;
133 const uint8_t *idct_permutation = s->idsp.idct_permutation;
134 int i, last, len, factor2;
135
136 for (i = !flag; i < 64; i++) {
137 int value;
138
139 value = get_vlc2(gb, block_tab, BLOCK_VLC_BITS, 1);
140 if (value < 0)
141 return AVERROR_INVALIDDATA;
142 if (value == 0) {
143 last = get_bits1(gb);
144 len = get_bits(gb, 6);
145 factor2 = get_sbits(gb, 8);
146 } else {
147 factor2 = value & 0x7F;
148 last = (value >> 14) & 1;
149 len = (value >> 7) & 0x3F;
150 if (get_bits1(gb))
151 factor2 = -factor2;
152 }
153 i += len;
154 if (i >= 64)
155 break;
156 s->block[block][idct_permutation[i]] = offset * (factor2 < 0 ? -1 : 1) + factor * factor2;
157 if (last)
158 break;
159 }
160
161 if (s->hi == 2 && flag2 && block < 4) {
162 if (flag)
163 s->block[block][idct_permutation[0]] *= 2;
164 s->block[block][idct_permutation[1]] *= 2;
165 s->block[block][idct_permutation[8]] *= 2;
166 s->block[block][idct_permutation[16]] *= 2;
167 }
168
169 return 0;
170 }
171
172 static int decode_blocks(AVCodecContext *avctx, GetBitContext *gb,
173 unsigned cbp, int flag, int offset, unsigned flag2)
174 {
175 IMM4Context *s = avctx->priv_data;
176 const uint8_t *idct_permutation = s->idsp.idct_permutation;
177 int ret, i;
178
179 memset(s->block, 0, sizeof(s->block));
180
181 for (i = 0; i < 6; i++) {
182 if (!flag) {
183 int x = get_bits(gb, 8);
184
185 if (x == 255)
186 x = 128;
187 x *= 8;
188
189 s->block[i][idct_permutation[0]] = x;
190 }
191
192 if (cbp & (1 << (5 - i))) {
193 ret = decode_block(avctx, gb, i, s->factor, flag, offset, flag2);
194 if (ret < 0)
195 return ret;
196 }
197 }
198
199 return 0;
200 }
201
202 static int decode_intra(AVCodecContext *avctx, GetBitContext *gb, AVFrame *frame)
203 {
204 IMM4Context *s = avctx->priv_data;
205 int ret, x, y, offset = 0;
206
207 if (s->hi == 0) {
208 if (s->lo > 2)
209 return AVERROR_INVALIDDATA;
210 s->factor = intra_cb[s->lo];
211 } else {
212 s->factor = s->lo * 2;
213 }
214
215 if (s->hi) {
216 offset = s->factor;
217 offset >>= 1;
218 if (!(offset & 1))
219 offset--;
220 }
221
222 for (y = 0; y < avctx->height; y += 16) {
223 for (x = 0; x < avctx->width; x += 16) {
224 unsigned flag, cbplo;
225 int cbphi;
226
227 cbplo = get_vlc2(gb, cbplo_tab, CBPLO_VLC_BITS, 1);
228 flag = get_bits1(gb);
229
230 cbphi = get_cbphi(gb, 1);
231 if (cbphi < 0)
232 return cbphi;
233
234 ret = decode_blocks(avctx, gb, cbplo | (cbphi << 2), 0, offset, flag);
235 if (ret < 0)
236 return ret;
237
238 s->idsp.idct_put(frame->data[0] + y * frame->linesize[0] + x,
239 frame->linesize[0], s->block[0]);
240 s->idsp.idct_put(frame->data[0] + y * frame->linesize[0] + x + 8,
241 frame->linesize[0], s->block[1]);
242 s->idsp.idct_put(frame->data[0] + (y + 8) * frame->linesize[0] + x,
243 frame->linesize[0], s->block[2]);
244 s->idsp.idct_put(frame->data[0] + (y + 8) * frame->linesize[0] + x + 8,
245 frame->linesize[0], s->block[3]);
246 s->idsp.idct_put(frame->data[1] + (y >> 1) * frame->linesize[1] + (x >> 1),
247 frame->linesize[1], s->block[4]);
248 s->idsp.idct_put(frame->data[2] + (y >> 1) * frame->linesize[2] + (x >> 1),
249 frame->linesize[2], s->block[5]);
250 }
251 }
252
253 return 0;
254 }
255
256 static int decode_inter(AVCodecContext *avctx, GetBitContext *gb,
257 AVFrame *frame, AVFrame *prev)
258 {
259 IMM4Context *s = avctx->priv_data;
260 int ret, x, y, offset = 0;
261
262 if (s->hi == 0) {
263 if (s->lo > 2)
264 return AVERROR_INVALIDDATA;
265 s->factor = inter_cb[s->lo];
266 } else {
267 s->factor = s->lo * 2;
268 }
269
270 if (s->hi) {
271 offset = s->factor;
272 offset >>= 1;
273 if (!(offset & 1))
274 offset--;
275 }
276
277 for (y = 0; y < avctx->height; y += 16) {
278 for (x = 0; x < avctx->width; x += 16) {
279 int reverse, intra_block, value;
280 unsigned cbplo, flag2 = 0;
281 int cbphi;
282
283 if (get_bits1(gb)) {
284 copy_block16(frame->data[0] + y * frame->linesize[0] + x,
285 prev->data[0] + y * prev->linesize[0] + x,
286 frame->linesize[0], prev->linesize[0], 16);
287 copy_block8(frame->data[1] + (y >> 1) * frame->linesize[1] + (x >> 1),
288 prev->data[1] + (y >> 1) * prev->linesize[1] + (x >> 1),
289 frame->linesize[1], prev->linesize[1], 8);
290 copy_block8(frame->data[2] + (y >> 1) * frame->linesize[2] + (x >> 1),
291 prev->data[2] + (y >> 1) * prev->linesize[2] + (x >> 1),
292 frame->linesize[2], prev->linesize[2], 8);
293 continue;
294 }
295
296 value = get_vlc2(gb, blktype_tab, BLKTYPE_VLC_BITS, 1);
297 if (value < 0)
298 return AVERROR_INVALIDDATA;
299
300 intra_block = value & 0x07;
301 reverse = intra_block == 3;
302 if (reverse)
303 flag2 = get_bits1(gb);
304
305 cbplo = value >> 4;
306 cbphi = get_cbphi(gb, reverse);
307 if (cbphi < 0)
308 return cbphi;
309
310 if (intra_block) {
311 ret = decode_blocks(avctx, gb, cbplo | (cbphi << 2), 0, offset, flag2);
312 if (ret < 0)
313 return ret;
314
315 s->idsp.idct_put(frame->data[0] + y * frame->linesize[0] + x,
316 frame->linesize[0], s->block[0]);
317 s->idsp.idct_put(frame->data[0] + y * frame->linesize[0] + x + 8,
318 frame->linesize[0], s->block[1]);
319 s->idsp.idct_put(frame->data[0] + (y + 8) * frame->linesize[0] + x,
320 frame->linesize[0], s->block[2]);
321 s->idsp.idct_put(frame->data[0] + (y + 8) * frame->linesize[0] + x + 8,
322 frame->linesize[0], s->block[3]);
323 s->idsp.idct_put(frame->data[1] + (y >> 1) * frame->linesize[1] + (x >> 1),
324 frame->linesize[1], s->block[4]);
325 s->idsp.idct_put(frame->data[2] + (y >> 1) * frame->linesize[2] + (x >> 1),
326 frame->linesize[2], s->block[5]);
327 } else {
328 flag2 = get_bits1(gb);
329 skip_bits1(gb);
330 ret = decode_blocks(avctx, gb, cbplo | (cbphi << 2), 1, offset, flag2);
331 if (ret < 0)
332 return ret;
333
334 copy_block16(frame->data[0] + y * frame->linesize[0] + x,
335 prev->data[0] + y * prev->linesize[0] + x,
336 frame->linesize[0], prev->linesize[0], 16);
337 copy_block8(frame->data[1] + (y >> 1) * frame->linesize[1] + (x >> 1),
338 prev->data[1] + (y >> 1) * prev->linesize[1] + (x >> 1),
339 frame->linesize[1], prev->linesize[1], 8);
340 copy_block8(frame->data[2] + (y >> 1) * frame->linesize[2] + (x >> 1),
341 prev->data[2] + (y >> 1) * prev->linesize[2] + (x >> 1),
342 frame->linesize[2], prev->linesize[2], 8);
343
344 s->idsp.idct_add(frame->data[0] + y * frame->linesize[0] + x,
345 frame->linesize[0], s->block[0]);
346 s->idsp.idct_add(frame->data[0] + y * frame->linesize[0] + x + 8,
347 frame->linesize[0], s->block[1]);
348 s->idsp.idct_add(frame->data[0] + (y + 8) * frame->linesize[0] + x,
349 frame->linesize[0], s->block[2]);
350 s->idsp.idct_add(frame->data[0] + (y + 8) * frame->linesize[0] + x + 8,
351 frame->linesize[0], s->block[3]);
352 s->idsp.idct_add(frame->data[1] + (y >> 1) * frame->linesize[1] + (x >> 1),
353 frame->linesize[1], s->block[4]);
354 s->idsp.idct_add(frame->data[2] + (y >> 1) * frame->linesize[2] + (x >> 1),
355 frame->linesize[2], s->block[5]);
356 }
357 }
358 }
359
360 return 0;
361 }
362
363 static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
364 int *got_frame, AVPacket *avpkt)
365 {
366 IMM4Context *s = avctx->priv_data;
367 GetBitContext *gb = &s->gb;
368 int width, height;
369 unsigned type;
370 int ret, scaled;
371
372 if (avpkt->size <= 32)
373 return AVERROR_INVALIDDATA;
374
375 av_fast_padded_malloc(&s->bitstream, &s->bitstream_size,
376 FFALIGN(avpkt->size, 4));
377 if (!s->bitstream)
378 return AVERROR(ENOMEM);
379
380 s->bdsp.bswap_buf((uint32_t *)s->bitstream,
381 (uint32_t *)avpkt->data,
382 (avpkt->size + 3) >> 2);
383
384 if ((ret = init_get_bits8(gb, s->bitstream, FFALIGN(avpkt->size, 4))) < 0)
385 return ret;
386
387 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
388 avctx->color_range = AVCOL_RANGE_JPEG;
389
390 width = avctx->width;
391 height = avctx->height;
392
393 scaled = avpkt->data[8];
394 if (scaled < 2) {
395 int mode = avpkt->data[10];
396
397 switch (mode) {
398 case 1:
399 width = 352;
400 height = 240;
401 break;
402 case 2:
403 width = 704;
404 height = 240;
405 break;
406 case 4:
407 width = 480;
408 height = 704;
409 break;
410 case 17:
411 width = 352;
412 height = 288;
413 break;
414 case 18:
415 width = 704;
416 height = 288;
417 break;
418 default:
419 width = 704;
420 height = 576;
421 break;
422 }
423 }
424
425 skip_bits_long(gb, 24 * 8);
426 type = get_bits_long(gb, 32);
427 s->hi = get_bits(gb, 16);
428 s->lo = get_bits(gb, 16);
429
430 switch (type) {
431 case 0x19781977:
432 frame->flags |= AV_FRAME_FLAG_KEY;
433 frame->pict_type = AV_PICTURE_TYPE_I;
434 break;
435 case 0x12250926:
436 frame->flags &= ~AV_FRAME_FLAG_KEY;
437 frame->pict_type = AV_PICTURE_TYPE_P;
438 break;
439 default:
440 avpriv_request_sample(avctx, "type %X", type);
441 return AVERROR_PATCHWELCOME;
442 }
443
444 if (avctx->width != width ||
445 avctx->height != height) {
446 if (!(frame->flags & AV_FRAME_FLAG_KEY)) {
447 av_log(avctx, AV_LOG_ERROR, "Frame size change is unsupported.\n");
448 return AVERROR_INVALIDDATA;
449 }
450 av_frame_unref(s->prev_frame);
451 }
452
453 ret = ff_set_dimensions(avctx, width, height);
454 if (ret < 0)
455 return ret;
456
457 if (((avctx->width + 15) / 16) * ((avctx->height + 15) / 16) > get_bits_left(gb))
458 return AVERROR_INVALIDDATA;
459
460
461 if ((ret = ff_get_buffer(avctx, frame, (frame->flags & AV_FRAME_FLAG_KEY) ? AV_GET_BUFFER_FLAG_REF : 0)) < 0)
462 return ret;
463
464 if (frame->flags & AV_FRAME_FLAG_KEY) {
465 ret = decode_intra(avctx, gb, frame);
466 if (ret < 0)
467 return ret;
468
469 if ((ret = av_frame_replace(s->prev_frame, frame)) < 0)
470 return ret;
471 } else {
472 if (!s->prev_frame->data[0]) {
473 av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n");
474 return AVERROR_INVALIDDATA;
475 }
476
477 ret = decode_inter(avctx, gb, frame, s->prev_frame);
478 if (ret < 0)
479 return ret;
480 }
481
482 *got_frame = 1;
483
484 return avpkt->size;
485 }
486
487 static av_cold void imm4_init_static_data(void)
488 {
489 VLC_INIT_STATIC_TABLE_FROM_LENGTHS(cbplo_tab, CBPLO_VLC_BITS, FF_ARRAY_ELEMS(cbplo),
490 &cbplo[0][1], 2, &cbplo[0][0], 2, 1,
491 0, 0);
492
493 VLC_INIT_STATIC_TABLE(cbphi_tab, CBPHI_VLC_BITS, FF_ARRAY_ELEMS(cbphi_bits),
494 cbphi_bits, 1, 1, cbphi_codes, 1, 1, 0);
495
496 VLC_INIT_STATIC_TABLE_FROM_LENGTHS(blktype_tab, BLKTYPE_VLC_BITS, FF_ARRAY_ELEMS(blktype),
497 &blktype[0][1], 2, &blktype[0][0], 2, 1,
498 0, 0);
499
500 VLC_INIT_STATIC_TABLE_FROM_LENGTHS(block_tab, BLOCK_VLC_BITS, FF_ARRAY_ELEMS(block_bits),
501 block_bits, 1, block_symbols, 2, 2,
502 0, 0);
503 }
504
505 static av_cold int decode_init(AVCodecContext *avctx)
506 {
507 static AVOnce init_static_once = AV_ONCE_INIT;
508 IMM4Context *s = avctx->priv_data;
509
510 ff_bswapdsp_init(&s->bdsp);
511 ff_idctdsp_init(&s->idsp, avctx);
512
513 s->prev_frame = av_frame_alloc();
514 if (!s->prev_frame)
515 return AVERROR(ENOMEM);
516
517 ff_thread_once(&init_static_once, imm4_init_static_data);
518
519 return 0;
520 }
521
522 static av_cold void decode_flush(AVCodecContext *avctx)
523 {
524 IMM4Context *s = avctx->priv_data;
525
526 av_frame_unref(s->prev_frame);
527 }
528
529 static av_cold int decode_close(AVCodecContext *avctx)
530 {
531 IMM4Context *s = avctx->priv_data;
532
533 av_frame_free(&s->prev_frame);
534 av_freep(&s->bitstream);
535 s->bitstream_size = 0;
536
537 return 0;
538 }
539
540 const FFCodec ff_imm4_decoder = {
541 .p.name = "imm4",
542 CODEC_LONG_NAME("Infinity IMM4"),
543 .p.type = AVMEDIA_TYPE_VIDEO,
544 .p.id = AV_CODEC_ID_IMM4,
545 .priv_data_size = sizeof(IMM4Context),
546 .init = decode_init,
547 .close = decode_close,
548 FF_CODEC_DECODE_CB(decode_frame),
549 .flush = decode_flush,
550 .p.capabilities = AV_CODEC_CAP_DR1,
551 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
552 };
553