FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/utvideodec.c
Date: 2024-07-17 14:05:47
Exec Total Coverage
Lines: 363 640 56.7%
Functions: 10 11 90.9%
Branches: 171 337 50.7%

Line Branch Exec Source
1 /*
2 * Ut Video decoder
3 * Copyright (c) 2011 Konstantin Shishkov
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 * Ut Video decoder
25 */
26
27 #include <inttypes.h>
28 #include <stdlib.h>
29
30 #define CACHED_BITSTREAM_READER !ARCH_X86_32
31 #define UNCHECKED_BITSTREAM_READER 1
32
33 #include "libavutil/intreadwrite.h"
34 #include "libavutil/mem.h"
35 #include "libavutil/pixdesc.h"
36 #include "avcodec.h"
37 #include "bswapdsp.h"
38 #include "bytestream.h"
39 #include "codec_internal.h"
40 #include "get_bits.h"
41 #include "lossless_videodsp.h"
42 #include "thread.h"
43 #include "utvideo.h"
44 #include "utvideodsp.h"
45
46 typedef struct UtvideoContext {
47 AVCodecContext *avctx;
48 UTVideoDSPContext utdsp;
49 BswapDSPContext bdsp;
50 LLVidDSPContext llviddsp;
51
52 uint32_t frame_info_size, flags, frame_info, offset;
53 int planes;
54 int slices;
55 int compression;
56 int interlaced;
57 int frame_pred;
58 int pro;
59 int pack;
60
61 uint8_t *slice_bits;
62 int slice_bits_size;
63 void *buffer;
64
65 const uint8_t *packed_stream[4][256];
66 size_t packed_stream_size[4][256];
67 const uint8_t *control_stream[4][256];
68 size_t control_stream_size[4][256];
69 } UtvideoContext;
70
71 typedef struct HuffEntry {
72 uint8_t len;
73 uint16_t sym;
74 } HuffEntry;
75
76 183 static int build_huff(UtvideoContext *c, const uint8_t *src, VLC *vlc,
77 VLC_MULTI *multi, int *fsym, unsigned nb_elems)
78 {
79 int i;
80 HuffEntry he[1024];
81 uint8_t bits[1024];
82 183 uint16_t codes_count[33] = { 0 };
83
84 183 *fsym = -1;
85
2/2
✓ Branch 0 taken 46387 times.
✓ Branch 1 taken 179 times.
46566 for (i = 0; i < nb_elems; i++) {
86
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 46383 times.
46387 if (src[i] == 0) {
87 4 *fsym = i;
88 4 return 0;
89
2/2
✓ Branch 0 taken 18630 times.
✓ Branch 1 taken 27753 times.
46383 } else if (src[i] == 255) {
90 18630 bits[i] = 0;
91
1/2
✓ Branch 0 taken 27753 times.
✗ Branch 1 not taken.
27753 } else if (src[i] <= 32) {
92 27753 bits[i] = src[i];
93 } else
94 return AVERROR_INVALIDDATA;
95
96 46383 codes_count[bits[i]]++;
97 }
98
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 179 times.
179 if (codes_count[0] == nb_elems)
99 return AVERROR_INVALIDDATA;
100
101 /* For Ut Video, longer codes are to the left of the tree and
102 * for codes with the same length the symbol is descending from
103 * left to right. So after the next loop --codes_count[i] will
104 * be the index of the first (lowest) symbol of length i when
105 * indexed by the position in the tree with left nodes being first. */
106
2/2
✓ Branch 0 taken 5728 times.
✓ Branch 1 taken 179 times.
5907 for (int i = 31; i >= 0; i--)
107 5728 codes_count[i] += codes_count[i + 1];
108
109
2/2
✓ Branch 0 taken 45824 times.
✓ Branch 1 taken 179 times.
46003 for (unsigned i = 0; i < nb_elems; i++)
110 45824 he[--codes_count[bits[i]]] = (HuffEntry) { bits[i], i };
111
112 #define VLC_BITS 11
113 179 return ff_vlc_init_multi_from_lengths(vlc, multi, VLC_BITS, nb_elems, codes_count[0],
114 &he[0].len, sizeof(*he),
115 179 &he[0].sym, sizeof(*he), 2, 0, 0, c->avctx);
116 }
117
118 #define READ_PLANE(b, end) \
119 { \
120 buf = !use_pred ? dest : c->buffer; \
121 i = 0; \
122 for (; CACHED_BITSTREAM_READER && i < width-end && get_bits_left(&gb) > 0;) {\
123 ret = get_vlc_multi(&gb, (uint8_t *)buf + i * b, multi.table, \
124 vlc.table, VLC_BITS, 3, b); \
125 if (ret > 0) \
126 i += ret; \
127 if (ret <= 0) \
128 goto fail; \
129 } \
130 for (; i < width && get_bits_left(&gb) > 0; i++) \
131 buf[i] = get_vlc2(&gb, vlc.table, VLC_BITS, 3); \
132 if (use_pred) { \
133 if (b == 2) \
134 c->llviddsp.add_left_pred_int16((uint16_t *)dest, (const uint16_t *)buf, 0x3ff, width, prev); \
135 else \
136 c->llviddsp.add_left_pred((uint8_t *)dest, (const uint8_t *)buf, width, prev); \
137 } \
138 prev = dest[width-1]; \
139 dest += stride; \
140 }
141
142 static int decode_plane10(UtvideoContext *c, int plane_no,
143 uint16_t *dst, ptrdiff_t stride,
144 int width, int height,
145 const uint8_t *src, const uint8_t *huff,
146 int use_pred)
147 {
148 int i, j, slice, pix, ret;
149 int sstart, send;
150 VLC_MULTI multi;
151 VLC vlc;
152 GetBitContext gb;
153 int prev, fsym;
154
155 if ((ret = build_huff(c, huff, &vlc, &multi, &fsym, 1024)) < 0) {
156 av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n");
157 return ret;
158 }
159 if (fsym >= 0) { // build_huff reported a symbol to fill slices with
160 send = 0;
161 for (slice = 0; slice < c->slices; slice++) {
162 uint16_t *dest;
163
164 sstart = send;
165 send = (height * (slice + 1) / c->slices);
166 dest = dst + sstart * stride;
167
168 prev = 0x200;
169 for (j = sstart; j < send; j++) {
170 for (i = 0; i < width; i++) {
171 pix = fsym;
172 if (use_pred) {
173 prev += pix;
174 prev &= 0x3FF;
175 pix = prev;
176 }
177 dest[i] = pix;
178 }
179 dest += stride;
180 }
181 }
182 return 0;
183 }
184
185 send = 0;
186 for (slice = 0; slice < c->slices; slice++) {
187 uint16_t *dest, *buf;
188 int slice_data_start, slice_data_end, slice_size;
189
190 sstart = send;
191 send = (height * (slice + 1) / c->slices);
192 dest = dst + sstart * stride;
193
194 // slice offset and size validation was done earlier
195 slice_data_start = slice ? AV_RL32(src + slice * 4 - 4) : 0;
196 slice_data_end = AV_RL32(src + slice * 4);
197 slice_size = slice_data_end - slice_data_start;
198
199 if (!slice_size) {
200 av_log(c->avctx, AV_LOG_ERROR, "Plane has more than one symbol "
201 "yet a slice has a length of zero.\n");
202 goto fail;
203 }
204
205 memset(c->slice_bits + slice_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
206 c->bdsp.bswap_buf((uint32_t *) c->slice_bits,
207 (uint32_t *)(src + slice_data_start + c->slices * 4),
208 (slice_data_end - slice_data_start + 3) >> 2);
209 init_get_bits(&gb, c->slice_bits, slice_size * 8);
210
211 prev = 0x200;
212 for (j = sstart; j < send; j++)
213 READ_PLANE(2, 3)
214 if (get_bits_left(&gb) > 32)
215 av_log(c->avctx, AV_LOG_WARNING,
216 "%d bits left after decoding slice\n", get_bits_left(&gb));
217 }
218
219 ff_vlc_free(&vlc);
220 ff_vlc_free_multi(&multi);
221
222 return 0;
223 fail:
224 ff_vlc_free(&vlc);
225 ff_vlc_free_multi(&multi);
226 return AVERROR_INVALIDDATA;
227 }
228
229 183 static int compute_cmask(int plane_no, int interlaced, enum AVPixelFormat pix_fmt)
230 {
231
4/4
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 141 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 28 times.
183 const int is_luma = (pix_fmt == AV_PIX_FMT_YUV420P) && !plane_no;
232
233
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 159 times.
183 if (interlaced)
234 24 return ~(1 + 2 * is_luma);
235
236 159 return ~is_luma;
237 }
238
239 183 static int decode_plane(UtvideoContext *c, int plane_no,
240 uint8_t *dst, ptrdiff_t stride,
241 int width, int height,
242 const uint8_t *src, int use_pred)
243 {
244 int i, j, slice, pix;
245 int sstart, send;
246 VLC_MULTI multi;
247 VLC vlc;
248 GetBitContext gb;
249 int ret, prev, fsym;
250 183 const int cmask = compute_cmask(plane_no, c->interlaced, c->avctx->pix_fmt);
251
252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 183 times.
183 if (c->pack) {
253 send = 0;
254 for (slice = 0; slice < c->slices; slice++) {
255 GetBitContext cbit, pbit;
256 uint8_t *dest, *p;
257
258 ret = init_get_bits8_le(&cbit, c->control_stream[plane_no][slice], c->control_stream_size[plane_no][slice]);
259 if (ret < 0)
260 return ret;
261
262 ret = init_get_bits8_le(&pbit, c->packed_stream[plane_no][slice], c->packed_stream_size[plane_no][slice]);
263 if (ret < 0)
264 return ret;
265
266 sstart = send;
267 send = (height * (slice + 1) / c->slices) & cmask;
268 dest = dst + sstart * stride;
269
270 if (3 * ((dst + send * stride - dest + 7)/8) > get_bits_left(&cbit))
271 return AVERROR_INVALIDDATA;
272
273 for (p = dest; p < dst + send * stride; p += 8) {
274 int bits = get_bits_le(&cbit, 3);
275
276 if (bits == 0) {
277 *(uint64_t *) p = 0;
278 } else {
279 uint32_t sub = 0x80 >> (8 - (bits + 1)), add;
280 int k;
281
282 if ((bits + 1) * 8 > get_bits_left(&pbit))
283 return AVERROR_INVALIDDATA;
284
285 for (k = 0; k < 8; k++) {
286
287 p[k] = get_bits_le(&pbit, bits + 1);
288 add = (~p[k] & sub) << (8 - bits);
289 p[k] -= sub;
290 p[k] += add;
291 }
292 }
293 }
294 }
295
296 return 0;
297 }
298
299
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 183 times.
183 if (build_huff(c, src, &vlc, &multi, &fsym, 256)) {
300 av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n");
301 return AVERROR_INVALIDDATA;
302 }
303
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 179 times.
183 if (fsym >= 0) { // build_huff reported a symbol to fill slices with
304 4 send = 0;
305
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (slice = 0; slice < c->slices; slice++) {
306 uint8_t *dest;
307
308 16 sstart = send;
309 16 send = (height * (slice + 1) / c->slices) & cmask;
310 16 dest = dst + sstart * stride;
311
312 16 prev = 0x80;
313
2/2
✓ Branch 0 taken 3072 times.
✓ Branch 1 taken 16 times.
3088 for (j = sstart; j < send; j++) {
314
2/2
✓ Branch 0 taken 3145728 times.
✓ Branch 1 taken 3072 times.
3148800 for (i = 0; i < width; i++) {
315 3145728 pix = fsym;
316
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3145728 times.
3145728 if (use_pred) {
317 prev += (unsigned)pix;
318 pix = prev;
319 }
320 3145728 dest[i] = pix;
321 }
322 3072 dest += stride;
323 }
324 }
325 4 return 0;
326 }
327
328 179 src += 256;
329
330 179 send = 0;
331
2/2
✓ Branch 0 taken 716 times.
✓ Branch 1 taken 179 times.
895 for (slice = 0; slice < c->slices; slice++) {
332 uint8_t *dest, *buf;
333 int slice_data_start, slice_data_end, slice_size;
334
335 716 sstart = send;
336 716 send = (height * (slice + 1) / c->slices) & cmask;
337 716 dest = dst + sstart * stride;
338
339 // slice offset and size validation was done earlier
340
2/2
✓ Branch 0 taken 537 times.
✓ Branch 1 taken 179 times.
716 slice_data_start = slice ? AV_RL32(src + slice * 4 - 4) : 0;
341 716 slice_data_end = AV_RL32(src + slice * 4);
342 716 slice_size = slice_data_end - slice_data_start;
343
344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 716 times.
716 if (!slice_size) {
345 av_log(c->avctx, AV_LOG_ERROR, "Plane has more than one symbol "
346 "yet a slice has a length of zero.\n");
347 goto fail;
348 }
349
350 716 memset(c->slice_bits + slice_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
351 716 c->bdsp.bswap_buf((uint32_t *) c->slice_bits,
352 716 (uint32_t *)(src + slice_data_start + c->slices * 4),
353 716 (slice_data_end - slice_data_start + 3) >> 2);
354 716 init_get_bits(&gb, c->slice_bits, slice_size * 8);
355
356 716 prev = 0x80;
357
2/2
✓ Branch 0 taken 63142 times.
✓ Branch 1 taken 716 times.
63858 for (j = sstart; j < send; j++)
358
12/16
✓ Branch 0 taken 27840 times.
✓ Branch 1 taken 35302 times.
✓ Branch 3 taken 7466839 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 7466839 times.
✓ Branch 7 taken 7466839 times.
✓ Branch 8 taken 63142 times.
✓ Branch 10 taken 7466839 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 187598 times.
✓ Branch 14 taken 63142 times.
✓ Branch 16 taken 187598 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 27840 times.
✓ Branch 19 taken 35302 times.
7717579 READ_PLANE(1, 5)
359
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 716 times.
716 if (get_bits_left(&gb) > 32)
360 av_log(c->avctx, AV_LOG_WARNING,
361 "%d bits left after decoding slice\n", get_bits_left(&gb));
362 }
363
364 179 ff_vlc_free(&vlc);
365 179 ff_vlc_free_multi(&multi);
366
367 179 return 0;
368 fail:
369 ff_vlc_free(&vlc);
370 ff_vlc_free_multi(&multi);
371 return AVERROR_INVALIDDATA;
372 }
373
374 #undef A
375 #undef B
376 #undef C
377
378 77 static void restore_median_planar(UtvideoContext *c, uint8_t *src, ptrdiff_t stride,
379 int width, int height, int slices, int rmode)
380 {
381 int i, j, slice;
382 int A, B, C;
383 uint8_t *bsrc;
384 int slice_start, slice_height;
385 77 const int cmask = ~rmode;
386
387
2/2
✓ Branch 0 taken 308 times.
✓ Branch 1 taken 77 times.
385 for (slice = 0; slice < slices; slice++) {
388 308 slice_start = ((slice * height) / slices) & cmask;
389 308 slice_height = ((((slice + 1) * height) / slices) & cmask) -
390 slice_start;
391
392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 308 times.
308 if (!slice_height)
393 continue;
394 308 bsrc = src + slice_start * stride;
395
396 // first line - left neighbour prediction
397 308 bsrc[0] += 0x80;
398 308 c->llviddsp.add_left_pred(bsrc, bsrc, width, 0);
399 308 bsrc += stride;
400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 308 times.
308 if (slice_height <= 1)
401 continue;
402 // second line - first element has top prediction, the rest uses median
403 308 C = bsrc[-stride];
404 308 bsrc[0] += C;
405 308 A = bsrc[0];
406
2/2
✓ Branch 0 taken 4620 times.
✓ Branch 1 taken 308 times.
4928 for (i = 1; i < FFMIN(width, 16); i++) { /* scalar loop (DSP need align 16) */
407 4620 B = bsrc[i - stride];
408 4620 bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C));
409 4620 C = B;
410 4620 A = bsrc[i];
411 }
412
1/2
✓ Branch 0 taken 308 times.
✗ Branch 1 not taken.
308 if (width > 16)
413 308 c->llviddsp.add_median_pred(bsrc + 16, bsrc - stride + 16,
414 308 bsrc + 16, width - 16, &A, &B);
415
416 308 bsrc += stride;
417 // the rest of lines use continuous median prediction
418
2/2
✓ Branch 0 taken 33128 times.
✓ Branch 1 taken 308 times.
33436 for (j = 2; j < slice_height; j++) {
419 33128 c->llviddsp.add_median_pred(bsrc, bsrc - stride,
420 bsrc, width, &A, &B);
421 33128 bsrc += stride;
422 }
423 }
424 77 }
425
426 /* UtVideo interlaced mode treats every two lines as a single one,
427 * so restoring function should take care of possible padding between
428 * two parts of the same "line".
429 */
430 12 static void restore_median_planar_il(UtvideoContext *c, uint8_t *src, ptrdiff_t stride,
431 int width, int height, int slices, int rmode)
432 {
433 int i, j, slice;
434 int A, B, C;
435 uint8_t *bsrc;
436 int slice_start, slice_height;
437
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11 times.
12 const int cmask = ~(rmode ? 3 : 1);
438 12 const ptrdiff_t stride2 = stride << 1;
439
440
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 12 times.
60 for (slice = 0; slice < slices; slice++) {
441 48 slice_start = ((slice * height) / slices) & cmask;
442 48 slice_height = ((((slice + 1) * height) / slices) & cmask) -
443 slice_start;
444 48 slice_height >>= 1;
445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (!slice_height)
446 continue;
447
448 48 bsrc = src + slice_start * stride;
449
450 // first line - left neighbour prediction
451 48 bsrc[0] += 0x80;
452 48 A = c->llviddsp.add_left_pred(bsrc, bsrc, width, 0);
453 48 c->llviddsp.add_left_pred(bsrc + stride, bsrc + stride, width, A);
454 48 bsrc += stride2;
455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (slice_height <= 1)
456 continue;
457 // second line - first element has top prediction, the rest uses median
458 48 C = bsrc[-stride2];
459 48 bsrc[0] += C;
460 48 A = bsrc[0];
461
2/2
✓ Branch 0 taken 720 times.
✓ Branch 1 taken 48 times.
768 for (i = 1; i < FFMIN(width, 16); i++) { /* scalar loop (DSP need align 16) */
462 720 B = bsrc[i - stride2];
463 720 bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C));
464 720 C = B;
465 720 A = bsrc[i];
466 }
467
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (width > 16)
468 48 c->llviddsp.add_median_pred(bsrc + 16, bsrc - stride2 + 16,
469 48 bsrc + 16, width - 16, &A, &B);
470
471 48 c->llviddsp.add_median_pred(bsrc + stride, bsrc - stride,
472 48 bsrc + stride, width, &A, &B);
473 48 bsrc += stride2;
474 // the rest of lines use continuous median prediction
475
2/2
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 48 times.
216 for (j = 2; j < slice_height; j++) {
476 168 c->llviddsp.add_median_pred(bsrc, bsrc - stride2,
477 bsrc, width, &A, &B);
478 168 c->llviddsp.add_median_pred(bsrc + stride, bsrc - stride,
479 168 bsrc + stride, width, &A, &B);
480 168 bsrc += stride2;
481 }
482 }
483 12 }
484
485 13 static void restore_gradient_planar(UtvideoContext *c, uint8_t *src, ptrdiff_t stride,
486 int width, int height, int slices, int rmode)
487 {
488 int i, j, slice;
489 int A, B, C;
490 uint8_t *bsrc;
491 int slice_start, slice_height;
492 13 const int cmask = ~rmode;
493 13 int min_width = FFMIN(width, 32);
494
495
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 13 times.
65 for (slice = 0; slice < slices; slice++) {
496 52 slice_start = ((slice * height) / slices) & cmask;
497 52 slice_height = ((((slice + 1) * height) / slices) & cmask) -
498 slice_start;
499
500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (!slice_height)
501 continue;
502 52 bsrc = src + slice_start * stride;
503
504 // first line - left neighbour prediction
505 52 bsrc[0] += 0x80;
506 52 c->llviddsp.add_left_pred(bsrc, bsrc, width, 0);
507 52 bsrc += stride;
508
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (slice_height <= 1)
509 continue;
510
2/2
✓ Branch 0 taken 450 times.
✓ Branch 1 taken 52 times.
502 for (j = 1; j < slice_height; j++) {
511 // second line - first element has top prediction, the rest uses gradient
512 450 bsrc[0] = (bsrc[0] + bsrc[-stride]) & 0xFF;
513
2/2
✓ Branch 0 taken 13950 times.
✓ Branch 1 taken 450 times.
14400 for (i = 1; i < min_width; i++) { /* dsp need align 32 */
514 13950 A = bsrc[i - stride];
515 13950 B = bsrc[i - (stride + 1)];
516 13950 C = bsrc[i - 1];
517 13950 bsrc[i] = (A - B + C + bsrc[i]) & 0xFF;
518 }
519
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 128 times.
450 if (width > 32)
520 322 c->llviddsp.add_gradient_pred(bsrc + 32, stride, width - 32);
521 450 bsrc += stride;
522 }
523 }
524 13 }
525
526 12 static void restore_gradient_planar_il(UtvideoContext *c, uint8_t *src, ptrdiff_t stride,
527 int width, int height, int slices, int rmode)
528 {
529 int i, j, slice;
530 int A, B, C;
531 uint8_t *bsrc;
532 int slice_start, slice_height;
533
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11 times.
12 const int cmask = ~(rmode ? 3 : 1);
534 12 const ptrdiff_t stride2 = stride << 1;
535 12 int min_width = FFMIN(width, 32);
536
537
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 12 times.
60 for (slice = 0; slice < slices; slice++) {
538 48 slice_start = ((slice * height) / slices) & cmask;
539 48 slice_height = ((((slice + 1) * height) / slices) & cmask) -
540 slice_start;
541 48 slice_height >>= 1;
542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (!slice_height)
543 continue;
544
545 48 bsrc = src + slice_start * stride;
546
547 // first line - left neighbour prediction
548 48 bsrc[0] += 0x80;
549 48 A = c->llviddsp.add_left_pred(bsrc, bsrc, width, 0);
550 48 c->llviddsp.add_left_pred(bsrc + stride, bsrc + stride, width, A);
551 48 bsrc += stride2;
552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (slice_height <= 1)
553 continue;
554
2/2
✓ Branch 0 taken 216 times.
✓ Branch 1 taken 48 times.
264 for (j = 1; j < slice_height; j++) {
555 // second line - first element has top prediction, the rest uses gradient
556 216 bsrc[0] = (bsrc[0] + bsrc[-stride2]) & 0xFF;
557
2/2
✓ Branch 0 taken 6696 times.
✓ Branch 1 taken 216 times.
6912 for (i = 1; i < min_width; i++) { /* dsp need align 32 */
558 6696 A = bsrc[i - stride2];
559 6696 B = bsrc[i - (stride2 + 1)];
560 6696 C = bsrc[i - 1];
561 6696 bsrc[i] = (A - B + C + bsrc[i]) & 0xFF;
562 }
563
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 56 times.
216 if (width > 32)
564 160 c->llviddsp.add_gradient_pred(bsrc + 32, stride2, width - 32);
565
566 216 A = bsrc[-stride];
567 216 B = bsrc[-(1 + stride + stride - width)];
568 216 C = bsrc[width - 1];
569 216 bsrc[stride] = (A - B + C + bsrc[stride]) & 0xFF;
570
2/2
✓ Branch 0 taken 11816 times.
✓ Branch 1 taken 216 times.
12032 for (i = 1; i < width; i++) {
571 11816 A = bsrc[i - stride];
572 11816 B = bsrc[i - (1 + stride)];
573 11816 C = bsrc[i - 1 + stride];
574 11816 bsrc[i + stride] = (A - B + C + bsrc[i + stride]) & 0xFF;
575 }
576 216 bsrc += stride2;
577 }
578 }
579 12 }
580
581 57 static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
582 int *got_frame, AVPacket *avpkt)
583 {
584 57 const uint8_t *buf = avpkt->data;
585 57 int buf_size = avpkt->size;
586 57 UtvideoContext *c = avctx->priv_data;
587 int i, j;
588 const uint8_t *plane_start[5];
589 57 int plane_size, max_slice_size = 0, slice_start, slice_end, slice_size;
590 int ret;
591 GetByteContext gb;
592
593
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if ((ret = ff_thread_get_buffer(avctx, frame, 0)) < 0)
594 return ret;
595
596 /* parse plane structure to get frame flags and validate slice offsets */
597 57 bytestream2_init(&gb, buf, buf_size);
598
599
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (c->pack) {
600 const uint8_t *packed_stream;
601 const uint8_t *control_stream;
602 GetByteContext pb;
603 uint32_t nb_cbs;
604 int left;
605
606 c->frame_info = PRED_GRADIENT << 8;
607
608 if (bytestream2_get_byte(&gb) != 1)
609 return AVERROR_INVALIDDATA;
610 bytestream2_skip(&gb, 3);
611 c->offset = bytestream2_get_le32(&gb);
612
613 if (buf_size <= c->offset + 8LL)
614 return AVERROR_INVALIDDATA;
615
616 bytestream2_init(&pb, buf + 8 + c->offset, buf_size - 8 - c->offset);
617
618 nb_cbs = bytestream2_get_le32(&pb);
619 if (nb_cbs > c->offset)
620 return AVERROR_INVALIDDATA;
621
622 packed_stream = buf + 8;
623 control_stream = packed_stream + (c->offset - nb_cbs);
624 left = control_stream - packed_stream;
625
626 for (i = 0; i < c->planes; i++) {
627 for (j = 0; j < c->slices; j++) {
628 c->packed_stream[i][j] = packed_stream;
629 c->packed_stream_size[i][j] = bytestream2_get_le32(&pb);
630 if (c->packed_stream_size[i][j] > left)
631 return AVERROR_INVALIDDATA;
632 left -= c->packed_stream_size[i][j];
633 packed_stream += c->packed_stream_size[i][j];
634 }
635 }
636
637 left = buf + buf_size - control_stream;
638
639 for (i = 0; i < c->planes; i++) {
640 for (j = 0; j < c->slices; j++) {
641 c->control_stream[i][j] = control_stream;
642 c->control_stream_size[i][j] = bytestream2_get_le32(&pb);
643 if (c->control_stream_size[i][j] > left)
644 return AVERROR_INVALIDDATA;
645 left -= c->control_stream_size[i][j];
646 control_stream += c->control_stream_size[i][j];
647 }
648 }
649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 } else if (c->pro) {
650 if (bytestream2_get_bytes_left(&gb) < c->frame_info_size) {
651 av_log(avctx, AV_LOG_ERROR, "Not enough data for frame information\n");
652 return AVERROR_INVALIDDATA;
653 }
654 c->frame_info = bytestream2_get_le32u(&gb);
655 c->slices = ((c->frame_info >> 16) & 0xff) + 1;
656 for (i = 0; i < c->planes; i++) {
657 plane_start[i] = gb.buffer;
658 if (bytestream2_get_bytes_left(&gb) < 1024 + 4 * c->slices) {
659 av_log(avctx, AV_LOG_ERROR, "Insufficient data for a plane\n");
660 return AVERROR_INVALIDDATA;
661 }
662 slice_start = 0;
663 slice_end = 0;
664 for (j = 0; j < c->slices; j++) {
665 slice_end = bytestream2_get_le32u(&gb);
666 if (slice_end < 0 || slice_end < slice_start ||
667 bytestream2_get_bytes_left(&gb) < slice_end + 1024LL) {
668 av_log(avctx, AV_LOG_ERROR, "Incorrect slice size\n");
669 return AVERROR_INVALIDDATA;
670 }
671 slice_size = slice_end - slice_start;
672 slice_start = slice_end;
673 max_slice_size = FFMAX(max_slice_size, slice_size);
674 }
675 plane_size = slice_end;
676 bytestream2_skipu(&gb, plane_size);
677 bytestream2_skipu(&gb, 1024);
678 }
679 plane_start[c->planes] = gb.buffer;
680 } else {
681
2/2
✓ Branch 0 taken 183 times.
✓ Branch 1 taken 57 times.
240 for (i = 0; i < c->planes; i++) {
682 183 plane_start[i] = gb.buffer;
683
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 183 times.
183 if (bytestream2_get_bytes_left(&gb) < 256 + 4 * c->slices) {
684 av_log(avctx, AV_LOG_ERROR, "Insufficient data for a plane\n");
685 return AVERROR_INVALIDDATA;
686 }
687 183 bytestream2_skipu(&gb, 256);
688 183 slice_start = 0;
689 183 slice_end = 0;
690
2/2
✓ Branch 0 taken 732 times.
✓ Branch 1 taken 183 times.
915 for (j = 0; j < c->slices; j++) {
691 732 slice_end = bytestream2_get_le32u(&gb);
692
3/6
✓ Branch 0 taken 732 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 732 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 732 times.
1464 if (slice_end < 0 || slice_end < slice_start ||
693 732 bytestream2_get_bytes_left(&gb) < slice_end) {
694 av_log(avctx, AV_LOG_ERROR, "Incorrect slice size\n");
695 return AVERROR_INVALIDDATA;
696 }
697 732 slice_size = slice_end - slice_start;
698 732 slice_start = slice_end;
699 732 max_slice_size = FFMAX(max_slice_size, slice_size);
700 }
701 183 plane_size = slice_end;
702 183 bytestream2_skipu(&gb, plane_size);
703 }
704 57 plane_start[c->planes] = gb.buffer;
705
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 if (bytestream2_get_bytes_left(&gb) < c->frame_info_size) {
706 av_log(avctx, AV_LOG_ERROR, "Not enough data for frame information\n");
707 return AVERROR_INVALIDDATA;
708 }
709 57 c->frame_info = bytestream2_get_le32u(&gb);
710 }
711 57 av_log(avctx, AV_LOG_DEBUG, "frame information flags %"PRIX32"\n",
712 c->frame_info);
713
714 57 c->frame_pred = (c->frame_info >> 8) & 3;
715
716 57 max_slice_size += 4*avctx->width;
717
718
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 if (!c->pack) {
719 57 av_fast_malloc(&c->slice_bits, &c->slice_bits_size,
720 57 max_slice_size + AV_INPUT_BUFFER_PADDING_SIZE);
721
722
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (!c->slice_bits) {
723 av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer\n");
724 return AVERROR(ENOMEM);
725 }
726 }
727
728
4/8
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
57 switch (c->avctx->pix_fmt) {
729 28 case AV_PIX_FMT_GBRP:
730 case AV_PIX_FMT_GBRAP:
731
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 28 times.
124 for (i = 0; i < c->planes; i++) {
732 96 ret = decode_plane(c, i, frame->data[i],
733 96 frame->linesize[i], avctx->width,
734 avctx->height, plane_start[i],
735 96 c->frame_pred == PRED_LEFT);
736
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 if (ret)
737 return ret;
738
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 43 times.
96 if (c->frame_pred == PRED_MEDIAN) {
739
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 3 times.
53 if (!c->interlaced) {
740 50 restore_median_planar(c, frame->data[i],
741 50 frame->linesize[i], avctx->width,
742 avctx->height, c->slices, 0);
743 } else {
744 3 restore_median_planar_il(c, frame->data[i],
745 3 frame->linesize[i],
746 avctx->width, avctx->height, c->slices,
747 0);
748 }
749
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 36 times.
43 } else if (c->frame_pred == PRED_GRADIENT) {
750
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (!c->interlaced) {
751 4 restore_gradient_planar(c, frame->data[i],
752 4 frame->linesize[i], avctx->width,
753 avctx->height, c->slices, 0);
754 } else {
755 3 restore_gradient_planar_il(c, frame->data[i],
756 3 frame->linesize[i],
757 avctx->width, avctx->height, c->slices,
758 0);
759 }
760 }
761 }
762 28 c->utdsp.restore_rgb_planes(frame->data[2], frame->data[0], frame->data[1],
763 28 frame->linesize[2], frame->linesize[0], frame->linesize[1],
764 avctx->width, avctx->height);
765 28 break;
766 case AV_PIX_FMT_GBRAP10:
767 case AV_PIX_FMT_GBRP10:
768 for (i = 0; i < c->planes; i++) {
769 ret = decode_plane10(c, i, (uint16_t *)frame->data[i],
770 frame->linesize[i] / 2, avctx->width,
771 avctx->height, plane_start[i],
772 plane_start[i + 1] - 1024,
773 c->frame_pred == PRED_LEFT);
774 if (ret)
775 return ret;
776 }
777 c->utdsp.restore_rgb_planes10((uint16_t *)frame->data[2], (uint16_t *)frame->data[0], (uint16_t *)frame->data[1],
778 frame->linesize[2] / 2, frame->linesize[0] / 2, frame->linesize[1] / 2,
779 avctx->width, avctx->height);
780 break;
781 14 case AV_PIX_FMT_YUV420P:
782
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 14 times.
56 for (i = 0; i < 3; i++) {
783 42 ret = decode_plane(c, i, frame->data[i], frame->linesize[i],
784 42 avctx->width >> !!i, avctx->height >> !!i,
785 42 plane_start[i], c->frame_pred == PRED_LEFT);
786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ret)
787 return ret;
788
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 27 times.
42 if (c->frame_pred == PRED_MEDIAN) {
789
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 3 times.
15 if (!c->interlaced) {
790 12 restore_median_planar(c, frame->data[i], frame->linesize[i],
791 12 avctx->width >> !!i, avctx->height >> !!i,
792 c->slices, !i);
793 } else {
794 3 restore_median_planar_il(c, frame->data[i], frame->linesize[i],
795 3 avctx->width >> !!i,
796 3 avctx->height >> !!i,
797 c->slices, !i);
798 }
799
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 21 times.
27 } else if (c->frame_pred == PRED_GRADIENT) {
800
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (!c->interlaced) {
801 3 restore_gradient_planar(c, frame->data[i], frame->linesize[i],
802 3 avctx->width >> !!i, avctx->height >> !!i,
803 c->slices, !i);
804 } else {
805 3 restore_gradient_planar_il(c, frame->data[i], frame->linesize[i],
806 3 avctx->width >> !!i,
807 3 avctx->height >> !!i,
808 c->slices, !i);
809 }
810 }
811 }
812 14 break;
813 11 case AV_PIX_FMT_YUV422P:
814
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 11 times.
44 for (i = 0; i < 3; i++) {
815 33 ret = decode_plane(c, i, frame->data[i], frame->linesize[i],
816 33 avctx->width >> !!i, avctx->height,
817 33 plane_start[i], c->frame_pred == PRED_LEFT);
818
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (ret)
819 return ret;
820
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 18 times.
33 if (c->frame_pred == PRED_MEDIAN) {
821
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 3 times.
15 if (!c->interlaced) {
822 12 restore_median_planar(c, frame->data[i], frame->linesize[i],
823 12 avctx->width >> !!i, avctx->height,
824 c->slices, 0);
825 } else {
826 3 restore_median_planar_il(c, frame->data[i], frame->linesize[i],
827 3 avctx->width >> !!i, avctx->height,
828 c->slices, 0);
829 }
830
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
18 } else if (c->frame_pred == PRED_GRADIENT) {
831
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (!c->interlaced) {
832 3 restore_gradient_planar(c, frame->data[i], frame->linesize[i],
833 3 avctx->width >> !!i, avctx->height,
834 c->slices, 0);
835 } else {
836 3 restore_gradient_planar_il(c, frame->data[i], frame->linesize[i],
837 3 avctx->width >> !!i, avctx->height,
838 c->slices, 0);
839 }
840 }
841 }
842 11 break;
843 4 case AV_PIX_FMT_YUV444P:
844
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
16 for (i = 0; i < 3; i++) {
845 12 ret = decode_plane(c, i, frame->data[i], frame->linesize[i],
846 avctx->width, avctx->height,
847 12 plane_start[i], c->frame_pred == PRED_LEFT);
848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret)
849 return ret;
850
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (c->frame_pred == PRED_MEDIAN) {
851
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (!c->interlaced) {
852 3 restore_median_planar(c, frame->data[i], frame->linesize[i],
853 avctx->width, avctx->height,
854 c->slices, 0);
855 } else {
856 3 restore_median_planar_il(c, frame->data[i], frame->linesize[i],
857 avctx->width, avctx->height,
858 c->slices, 0);
859 }
860
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 } else if (c->frame_pred == PRED_GRADIENT) {
861
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (!c->interlaced) {
862 3 restore_gradient_planar(c, frame->data[i], frame->linesize[i],
863 avctx->width, avctx->height,
864 c->slices, 0);
865 } else {
866 3 restore_gradient_planar_il(c, frame->data[i], frame->linesize[i],
867 avctx->width, avctx->height,
868 c->slices, 0);
869 }
870 }
871 }
872 4 break;
873 case AV_PIX_FMT_YUV420P10:
874 for (i = 0; i < 3; i++) {
875 ret = decode_plane10(c, i, (uint16_t *)frame->data[i], frame->linesize[i] / 2,
876 avctx->width >> !!i, avctx->height >> !!i,
877 plane_start[i], plane_start[i + 1] - 1024, c->frame_pred == PRED_LEFT);
878 if (ret)
879 return ret;
880 }
881 break;
882 case AV_PIX_FMT_YUV422P10:
883 for (i = 0; i < 3; i++) {
884 ret = decode_plane10(c, i, (uint16_t *)frame->data[i], frame->linesize[i] / 2,
885 avctx->width >> !!i, avctx->height,
886 plane_start[i], plane_start[i + 1] - 1024, c->frame_pred == PRED_LEFT);
887 if (ret)
888 return ret;
889 }
890 break;
891 }
892
893
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 49 times.
57 if (c->interlaced)
894 8 frame->flags |= AV_FRAME_FLAG_INTERLACED;
895
896 57 *got_frame = 1;
897
898 /* always report that the buffer was completely consumed */
899 57 return buf_size;
900 }
901
902 46 static av_cold int decode_init(AVCodecContext *avctx)
903 {
904 46 UtvideoContext * const c = avctx->priv_data;
905 int h_shift, v_shift;
906
907 46 c->avctx = avctx;
908
909 46 ff_utvideodsp_init(&c->utdsp);
910 46 ff_bswapdsp_init(&c->bdsp);
911 46 ff_llviddsp_init(&c->llviddsp);
912
913 46 c->slice_bits_size = 0;
914
915
7/19
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 6 times.
✓ Branch 10 taken 6 times.
✓ Branch 11 taken 8 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
46 switch (avctx->codec_tag) {
916 10 case MKTAG('U', 'L', 'R', 'G'):
917 10 c->planes = 3;
918 10 avctx->pix_fmt = AV_PIX_FMT_GBRP;
919 10 break;
920 8 case MKTAG('U', 'L', 'R', 'A'):
921 8 c->planes = 4;
922 8 avctx->pix_fmt = AV_PIX_FMT_GBRAP;
923 8 break;
924 4 case MKTAG('U', 'L', 'Y', '0'):
925 4 c->planes = 3;
926 4 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
927 4 avctx->colorspace = AVCOL_SPC_BT470BG;
928 4 break;
929 4 case MKTAG('U', 'L', 'Y', '2'):
930 4 c->planes = 3;
931 4 avctx->pix_fmt = AV_PIX_FMT_YUV422P;
932 4 avctx->colorspace = AVCOL_SPC_BT470BG;
933 4 break;
934 case MKTAG('U', 'L', 'Y', '4'):
935 c->planes = 3;
936 avctx->pix_fmt = AV_PIX_FMT_YUV444P;
937 avctx->colorspace = AVCOL_SPC_BT470BG;
938 break;
939 case MKTAG('U', 'Q', 'Y', '0'):
940 c->planes = 3;
941 c->pro = 1;
942 avctx->pix_fmt = AV_PIX_FMT_YUV420P10;
943 break;
944 case MKTAG('U', 'Q', 'Y', '2'):
945 c->planes = 3;
946 c->pro = 1;
947 avctx->pix_fmt = AV_PIX_FMT_YUV422P10;
948 break;
949 case MKTAG('U', 'Q', 'R', 'G'):
950 c->planes = 3;
951 c->pro = 1;
952 avctx->pix_fmt = AV_PIX_FMT_GBRP10;
953 break;
954 case MKTAG('U', 'Q', 'R', 'A'):
955 c->planes = 4;
956 c->pro = 1;
957 avctx->pix_fmt = AV_PIX_FMT_GBRAP10;
958 break;
959 6 case MKTAG('U', 'L', 'H', '0'):
960 6 c->planes = 3;
961 6 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
962 6 avctx->colorspace = AVCOL_SPC_BT709;
963 6 break;
964 6 case MKTAG('U', 'L', 'H', '2'):
965 6 c->planes = 3;
966 6 avctx->pix_fmt = AV_PIX_FMT_YUV422P;
967 6 avctx->colorspace = AVCOL_SPC_BT709;
968 6 break;
969 8 case MKTAG('U', 'L', 'H', '4'):
970 8 c->planes = 3;
971 8 avctx->pix_fmt = AV_PIX_FMT_YUV444P;
972 8 avctx->colorspace = AVCOL_SPC_BT709;
973 8 break;
974 case MKTAG('U', 'M', 'Y', '2'):
975 c->planes = 3;
976 c->pack = 1;
977 avctx->pix_fmt = AV_PIX_FMT_YUV422P;
978 avctx->colorspace = AVCOL_SPC_BT470BG;
979 break;
980 case MKTAG('U', 'M', 'H', '2'):
981 c->planes = 3;
982 c->pack = 1;
983 avctx->pix_fmt = AV_PIX_FMT_YUV422P;
984 avctx->colorspace = AVCOL_SPC_BT709;
985 break;
986 case MKTAG('U', 'M', 'Y', '4'):
987 c->planes = 3;
988 c->pack = 1;
989 avctx->pix_fmt = AV_PIX_FMT_YUV444P;
990 avctx->colorspace = AVCOL_SPC_BT470BG;
991 break;
992 case MKTAG('U', 'M', 'H', '4'):
993 c->planes = 3;
994 c->pack = 1;
995 avctx->pix_fmt = AV_PIX_FMT_YUV444P;
996 avctx->colorspace = AVCOL_SPC_BT709;
997 break;
998 case MKTAG('U', 'M', 'R', 'G'):
999 c->planes = 3;
1000 c->pack = 1;
1001 avctx->pix_fmt = AV_PIX_FMT_GBRP;
1002 break;
1003 case MKTAG('U', 'M', 'R', 'A'):
1004 c->planes = 4;
1005 c->pack = 1;
1006 avctx->pix_fmt = AV_PIX_FMT_GBRAP;
1007 break;
1008 default:
1009 av_log(avctx, AV_LOG_ERROR, "Unknown Ut Video FOURCC provided (%08X)\n",
1010 avctx->codec_tag);
1011 return AVERROR_INVALIDDATA;
1012 }
1013
1014 46 av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &h_shift, &v_shift);
1015
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 if ((avctx->width & ((1<<h_shift)-1)) ||
1016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 (avctx->height & ((1<<v_shift)-1))) {
1017 avpriv_request_sample(avctx, "Odd dimensions");
1018 return AVERROR_PATCHWELCOME;
1019 }
1020
1021
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
46 if (c->pack && avctx->extradata_size >= 16) {
1022 av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n",
1023 avctx->extradata[3], avctx->extradata[2],
1024 avctx->extradata[1], avctx->extradata[0]);
1025 av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n",
1026 AV_RB32(avctx->extradata + 4));
1027 c->compression = avctx->extradata[8];
1028 if (c->compression != 2)
1029 avpriv_request_sample(avctx, "Unknown compression type");
1030 c->slices = avctx->extradata[9] + 1;
1031
2/4
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
✗ Branch 3 not taken.
46 } else if (!c->pro && avctx->extradata_size >= 16) {
1032 46 av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n",
1033 46 avctx->extradata[3], avctx->extradata[2],
1034 46 avctx->extradata[1], avctx->extradata[0]);
1035 46 av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n",
1036 46 AV_RB32(avctx->extradata + 4));
1037 46 c->frame_info_size = AV_RL32(avctx->extradata + 8);
1038 46 c->flags = AV_RL32(avctx->extradata + 12);
1039
1040
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (c->frame_info_size != 4)
1041 avpriv_request_sample(avctx, "Frame info not 4 bytes");
1042 46 av_log(avctx, AV_LOG_DEBUG, "Encoding parameters %08"PRIX32"\n", c->flags);
1043 46 c->slices = (c->flags >> 24) + 1;
1044 46 c->compression = c->flags & 1;
1045 46 c->interlaced = c->flags & 0x800;
1046 } else if (c->pro && avctx->extradata_size == 8) {
1047 av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n",
1048 avctx->extradata[3], avctx->extradata[2],
1049 avctx->extradata[1], avctx->extradata[0]);
1050 av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n",
1051 AV_RB32(avctx->extradata + 4));
1052 c->interlaced = 0;
1053 c->frame_info_size = 4;
1054 } else {
1055 av_log(avctx, AV_LOG_ERROR,
1056 "Insufficient extradata size %d, should be at least 16\n",
1057 avctx->extradata_size);
1058 return AVERROR_INVALIDDATA;
1059 }
1060
1061
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 c->buffer = av_calloc(avctx->width + 8, c->pro?2:1);
1062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (!c->buffer)
1063 return AVERROR(ENOMEM);
1064
1065 46 return 0;
1066 }
1067
1068 46 static av_cold int decode_end(AVCodecContext *avctx)
1069 {
1070 46 UtvideoContext * const c = avctx->priv_data;
1071
1072 46 av_freep(&c->slice_bits);
1073 46 av_freep(&c->buffer);
1074
1075 46 return 0;
1076 }
1077
1078 const FFCodec ff_utvideo_decoder = {
1079 .p.name = "utvideo",
1080 CODEC_LONG_NAME("Ut Video"),
1081 .p.type = AVMEDIA_TYPE_VIDEO,
1082 .p.id = AV_CODEC_ID_UTVIDEO,
1083 .priv_data_size = sizeof(UtvideoContext),
1084 .init = decode_init,
1085 .close = decode_end,
1086 FF_CODEC_DECODE_CB(decode_frame),
1087 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
1088 };
1089