FFmpeg coverage


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