FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/imm4.c
Date: 2024-11-21 09:21:34
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/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, cbplo;
224 int cbphi;
225
226 cbplo = get_vlc2(gb, cbplo_tab, CBPLO_VLC_BITS, 1);
227 flag = get_bits1(gb);
228
229 cbphi = get_cbphi(gb, 1);
230 if (cbphi < 0)
231 return cbphi;
232
233 ret = decode_blocks(avctx, gb, cbplo | (cbphi << 2), 0, offset, flag);
234 if (ret < 0)
235 return ret;
236
237 s->idsp.idct_put(frame->data[0] + y * frame->linesize[0] + x,
238 frame->linesize[0], s->block[0]);
239 s->idsp.idct_put(frame->data[0] + y * frame->linesize[0] + x + 8,
240 frame->linesize[0], s->block[1]);
241 s->idsp.idct_put(frame->data[0] + (y + 8) * frame->linesize[0] + x,
242 frame->linesize[0], s->block[2]);
243 s->idsp.idct_put(frame->data[0] + (y + 8) * frame->linesize[0] + x + 8,
244 frame->linesize[0], s->block[3]);
245 s->idsp.idct_put(frame->data[1] + (y >> 1) * frame->linesize[1] + (x >> 1),
246 frame->linesize[1], s->block[4]);
247 s->idsp.idct_put(frame->data[2] + (y >> 1) * frame->linesize[2] + (x >> 1),
248 frame->linesize[2], s->block[5]);
249 }
250 }
251
252 return 0;
253 }
254
255 static int decode_inter(AVCodecContext *avctx, GetBitContext *gb,
256 AVFrame *frame, AVFrame *prev)
257 {
258 IMM4Context *s = avctx->priv_data;
259 int ret, x, y, offset = 0;
260
261 if (s->hi == 0) {
262 if (s->lo > 2)
263 return AVERROR_INVALIDDATA;
264 s->factor = inter_cb[s->lo];
265 } else {
266 s->factor = s->lo * 2;
267 }
268
269 if (s->hi) {
270 offset = s->factor;
271 offset >>= 1;
272 if (!(offset & 1))
273 offset--;
274 }
275
276 for (y = 0; y < avctx->height; y += 16) {
277 for (x = 0; x < avctx->width; x += 16) {
278 int reverse, intra_block, value;
279 unsigned cbplo, flag2 = 0;
280 int cbphi;
281
282 if (get_bits1(gb)) {
283 copy_block16(frame->data[0] + y * frame->linesize[0] + x,
284 prev->data[0] + y * prev->linesize[0] + x,
285 frame->linesize[0], prev->linesize[0], 16);
286 copy_block8(frame->data[1] + (y >> 1) * frame->linesize[1] + (x >> 1),
287 prev->data[1] + (y >> 1) * prev->linesize[1] + (x >> 1),
288 frame->linesize[1], prev->linesize[1], 8);
289 copy_block8(frame->data[2] + (y >> 1) * frame->linesize[2] + (x >> 1),
290 prev->data[2] + (y >> 1) * prev->linesize[2] + (x >> 1),
291 frame->linesize[2], prev->linesize[2], 8);
292 continue;
293 }
294
295 value = get_vlc2(gb, blktype_tab, BLKTYPE_VLC_BITS, 1);
296 if (value < 0)
297 return AVERROR_INVALIDDATA;
298
299 intra_block = value & 0x07;
300 reverse = intra_block == 3;
301 if (reverse)
302 flag2 = get_bits1(gb);
303
304 cbplo = value >> 4;
305 cbphi = get_cbphi(gb, reverse);
306 if (cbphi < 0)
307 return cbphi;
308
309 if (intra_block) {
310 ret = decode_blocks(avctx, gb, cbplo | (cbphi << 2), 0, offset, flag2);
311 if (ret < 0)
312 return ret;
313
314 s->idsp.idct_put(frame->data[0] + y * frame->linesize[0] + x,
315 frame->linesize[0], s->block[0]);
316 s->idsp.idct_put(frame->data[0] + y * frame->linesize[0] + x + 8,
317 frame->linesize[0], s->block[1]);
318 s->idsp.idct_put(frame->data[0] + (y + 8) * frame->linesize[0] + x,
319 frame->linesize[0], s->block[2]);
320 s->idsp.idct_put(frame->data[0] + (y + 8) * frame->linesize[0] + x + 8,
321 frame->linesize[0], s->block[3]);
322 s->idsp.idct_put(frame->data[1] + (y >> 1) * frame->linesize[1] + (x >> 1),
323 frame->linesize[1], s->block[4]);
324 s->idsp.idct_put(frame->data[2] + (y >> 1) * frame->linesize[2] + (x >> 1),
325 frame->linesize[2], s->block[5]);
326 } else {
327 flag2 = get_bits1(gb);
328 skip_bits1(gb);
329 ret = decode_blocks(avctx, gb, cbplo | (cbphi << 2), 1, offset, flag2);
330 if (ret < 0)
331 return ret;
332
333 copy_block16(frame->data[0] + y * frame->linesize[0] + x,
334 prev->data[0] + y * prev->linesize[0] + x,
335 frame->linesize[0], prev->linesize[0], 16);
336 copy_block8(frame->data[1] + (y >> 1) * frame->linesize[1] + (x >> 1),
337 prev->data[1] + (y >> 1) * prev->linesize[1] + (x >> 1),
338 frame->linesize[1], prev->linesize[1], 8);
339 copy_block8(frame->data[2] + (y >> 1) * frame->linesize[2] + (x >> 1),
340 prev->data[2] + (y >> 1) * prev->linesize[2] + (x >> 1),
341 frame->linesize[2], prev->linesize[2], 8);
342
343 s->idsp.idct_add(frame->data[0] + y * frame->linesize[0] + x,
344 frame->linesize[0], s->block[0]);
345 s->idsp.idct_add(frame->data[0] + y * frame->linesize[0] + x + 8,
346 frame->linesize[0], s->block[1]);
347 s->idsp.idct_add(frame->data[0] + (y + 8) * frame->linesize[0] + x,
348 frame->linesize[0], s->block[2]);
349 s->idsp.idct_add(frame->data[0] + (y + 8) * frame->linesize[0] + x + 8,
350 frame->linesize[0], s->block[3]);
351 s->idsp.idct_add(frame->data[1] + (y >> 1) * frame->linesize[1] + (x >> 1),
352 frame->linesize[1], s->block[4]);
353 s->idsp.idct_add(frame->data[2] + (y >> 1) * frame->linesize[2] + (x >> 1),
354 frame->linesize[2], s->block[5]);
355 }
356 }
357 }
358
359 return 0;
360 }
361
362 static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
363 int *got_frame, AVPacket *avpkt)
364 {
365 IMM4Context *s = avctx->priv_data;
366 GetBitContext *gb = &s->gb;
367 int width, height;
368 unsigned type;
369 int ret, scaled;
370
371 if (avpkt->size <= 32)
372 return AVERROR_INVALIDDATA;
373
374 av_fast_padded_malloc(&s->bitstream, &s->bitstream_size,
375 FFALIGN(avpkt->size, 4));
376 if (!s->bitstream)
377 return AVERROR(ENOMEM);
378
379 s->bdsp.bswap_buf((uint32_t *)s->bitstream,
380 (uint32_t *)avpkt->data,
381 (avpkt->size + 3) >> 2);
382
383 if ((ret = init_get_bits8(gb, s->bitstream, FFALIGN(avpkt->size, 4))) < 0)
384 return ret;
385
386 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
387 avctx->color_range = AVCOL_RANGE_JPEG;
388
389 width = avctx->width;
390 height = avctx->height;
391
392 scaled = avpkt->data[8];
393 if (scaled < 2) {
394 int mode = avpkt->data[10];
395
396 switch (mode) {
397 case 1:
398 width = 352;
399 height = 240;
400 break;
401 case 2:
402 width = 704;
403 height = 240;
404 break;
405 case 4:
406 width = 480;
407 height = 704;
408 break;
409 case 17:
410 width = 352;
411 height = 288;
412 break;
413 case 18:
414 width = 704;
415 height = 288;
416 break;
417 default:
418 width = 704;
419 height = 576;
420 break;
421 }
422 }
423
424 skip_bits_long(gb, 24 * 8);
425 type = get_bits_long(gb, 32);
426 s->hi = get_bits(gb, 16);
427 s->lo = get_bits(gb, 16);
428
429 switch (type) {
430 case 0x19781977:
431 frame->flags |= AV_FRAME_FLAG_KEY;
432 frame->pict_type = AV_PICTURE_TYPE_I;
433 break;
434 case 0x12250926:
435 frame->flags &= ~AV_FRAME_FLAG_KEY;
436 frame->pict_type = AV_PICTURE_TYPE_P;
437 break;
438 default:
439 avpriv_request_sample(avctx, "type %X", type);
440 return AVERROR_PATCHWELCOME;
441 }
442
443 if (avctx->width != width ||
444 avctx->height != height) {
445 if (!(frame->flags & AV_FRAME_FLAG_KEY)) {
446 av_log(avctx, AV_LOG_ERROR, "Frame size change is unsupported.\n");
447 return AVERROR_INVALIDDATA;
448 }
449 av_frame_unref(s->prev_frame);
450 }
451
452 ret = ff_set_dimensions(avctx, width, height);
453 if (ret < 0)
454 return ret;
455
456 if (((avctx->width + 15) / 16) * ((avctx->height + 15) / 16) > get_bits_left(gb))
457 return AVERROR_INVALIDDATA;
458
459
460 if ((ret = ff_get_buffer(avctx, frame, (frame->flags & AV_FRAME_FLAG_KEY) ? AV_GET_BUFFER_FLAG_REF : 0)) < 0)
461 return ret;
462
463 if (frame->flags & AV_FRAME_FLAG_KEY) {
464 ret = decode_intra(avctx, gb, frame);
465 if (ret < 0)
466 return ret;
467
468 if ((ret = av_frame_replace(s->prev_frame, frame)) < 0)
469 return ret;
470 } else {
471 if (!s->prev_frame->data[0]) {
472 av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n");
473 return AVERROR_INVALIDDATA;
474 }
475
476 ret = decode_inter(avctx, gb, frame, s->prev_frame);
477 if (ret < 0)
478 return ret;
479 }
480
481 *got_frame = 1;
482
483 return avpkt->size;
484 }
485
486 static av_cold void imm4_init_static_data(void)
487 {
488 VLC_INIT_STATIC_TABLE_FROM_LENGTHS(cbplo_tab, CBPLO_VLC_BITS, FF_ARRAY_ELEMS(cbplo),
489 &cbplo[0][1], 2, &cbplo[0][0], 2, 1,
490 0, 0);
491
492 VLC_INIT_STATIC_TABLE(cbphi_tab, CBPHI_VLC_BITS, FF_ARRAY_ELEMS(cbphi_bits),
493 cbphi_bits, 1, 1, cbphi_codes, 1, 1, 0);
494
495 VLC_INIT_STATIC_TABLE_FROM_LENGTHS(blktype_tab, BLKTYPE_VLC_BITS, FF_ARRAY_ELEMS(blktype),
496 &blktype[0][1], 2, &blktype[0][0], 2, 1,
497 0, 0);
498
499 VLC_INIT_STATIC_TABLE_FROM_LENGTHS(block_tab, BLOCK_VLC_BITS, FF_ARRAY_ELEMS(block_bits),
500 block_bits, 1, block_symbols, 2, 2,
501 0, 0);
502 }
503
504 static av_cold int decode_init(AVCodecContext *avctx)
505 {
506 static AVOnce init_static_once = AV_ONCE_INIT;
507 IMM4Context *s = avctx->priv_data;
508
509 ff_bswapdsp_init(&s->bdsp);
510 ff_idctdsp_init(&s->idsp, avctx);
511
512 s->prev_frame = av_frame_alloc();
513 if (!s->prev_frame)
514 return AVERROR(ENOMEM);
515
516 ff_thread_once(&init_static_once, imm4_init_static_data);
517
518 return 0;
519 }
520
521 static void decode_flush(AVCodecContext *avctx)
522 {
523 IMM4Context *s = avctx->priv_data;
524
525 av_frame_unref(s->prev_frame);
526 }
527
528 static av_cold int decode_close(AVCodecContext *avctx)
529 {
530 IMM4Context *s = avctx->priv_data;
531
532 av_frame_free(&s->prev_frame);
533 av_freep(&s->bitstream);
534 s->bitstream_size = 0;
535
536 return 0;
537 }
538
539 const FFCodec ff_imm4_decoder = {
540 .p.name = "imm4",
541 CODEC_LONG_NAME("Infinity IMM4"),
542 .p.type = AVMEDIA_TYPE_VIDEO,
543 .p.id = AV_CODEC_ID_IMM4,
544 .priv_data_size = sizeof(IMM4Context),
545 .init = decode_init,
546 .close = decode_close,
547 FF_CODEC_DECODE_CB(decode_frame),
548 .flush = decode_flush,
549 .p.capabilities = AV_CODEC_CAP_DR1,
550 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
551 };
552