FFmpeg coverage


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