Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * MagicYUV decoder | ||
3 | * Copyright (c) 2016 Paul B Mahol | ||
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 | #include <stdlib.h> | ||
23 | #include <string.h> | ||
24 | |||
25 | #define CACHED_BITSTREAM_READER !ARCH_X86_32 | ||
26 | |||
27 | #include "libavutil/mem.h" | ||
28 | #include "libavutil/pixdesc.h" | ||
29 | |||
30 | #include "avcodec.h" | ||
31 | #include "bytestream.h" | ||
32 | #include "codec_internal.h" | ||
33 | #include "decode.h" | ||
34 | #include "get_bits.h" | ||
35 | #include "lossless_videodsp.h" | ||
36 | #include "thread.h" | ||
37 | |||
38 | #define VLC_BITS 12 | ||
39 | |||
40 | typedef struct Slice { | ||
41 | uint32_t start; | ||
42 | uint32_t size; | ||
43 | } Slice; | ||
44 | |||
45 | typedef enum Prediction { | ||
46 | LEFT = 1, | ||
47 | GRADIENT, | ||
48 | MEDIAN, | ||
49 | } Prediction; | ||
50 | |||
51 | typedef struct HuffEntry { | ||
52 | uint8_t len; | ||
53 | uint16_t sym; | ||
54 | } HuffEntry; | ||
55 | |||
56 | typedef struct MagicYUVContext { | ||
57 | AVFrame *p; | ||
58 | int max; | ||
59 | int bps; | ||
60 | int slice_height; | ||
61 | int nb_slices; | ||
62 | int planes; // number of encoded planes in bitstream | ||
63 | int decorrelate; // postprocessing work | ||
64 | int color_matrix; // video color matrix | ||
65 | int flags; | ||
66 | int interlaced; // video is interlaced | ||
67 | const uint8_t *buf; // pointer to AVPacket->data | ||
68 | int hshift[4]; | ||
69 | int vshift[4]; | ||
70 | Slice *slices[4]; // slice bitstream positions for each plane | ||
71 | unsigned int slices_size[4]; // slice sizes for each plane | ||
72 | VLC vlc[4]; // VLC for each plane | ||
73 | VLC_MULTI multi[4]; // Buffer for joint VLC data | ||
74 | int (*magy_decode_slice)(AVCodecContext *avctx, void *tdata, | ||
75 | int j, int threadnr); | ||
76 | LLVidDSPContext llviddsp; | ||
77 | HuffEntry he[1 << 14]; | ||
78 | uint8_t len[1 << 14]; | ||
79 | } MagicYUVContext; | ||
80 | |||
81 | 42 | static int huff_build(AVCodecContext *avctx, | |
82 | const uint8_t len[], uint16_t codes_pos[33], | ||
83 | VLC *vlc, VLC_MULTI *multi, int nb_elems, void *logctx) | ||
84 | { | ||
85 | 42 | MagicYUVContext *s = avctx->priv_data; | |
86 | 42 | HuffEntry *he = s->he; | |
87 | |||
88 |
2/2✓ Branch 0 taken 1302 times.
✓ Branch 1 taken 42 times.
|
1344 | for (int i = 31; i > 0; i--) |
89 | 1302 | codes_pos[i] += codes_pos[i + 1]; | |
90 | |||
91 |
2/2✓ Branch 0 taken 10752 times.
✓ Branch 1 taken 42 times.
|
10794 | for (unsigned i = nb_elems; i-- > 0;) |
92 | 10752 | he[--codes_pos[len[i]]] = (HuffEntry){ len[i], i }; | |
93 | |||
94 | 42 | ff_vlc_free(vlc); | |
95 | 42 | ff_vlc_free_multi(multi); | |
96 | 84 | return ff_vlc_init_multi_from_lengths(vlc, multi, FFMIN(he[0].len, VLC_BITS), nb_elems, nb_elems, | |
97 | 42 | &he[0].len, sizeof(he[0]), | |
98 | 42 | &he[0].sym, sizeof(he[0]), sizeof(he[0].sym), | |
99 | 0, 0, logctx); | ||
100 | } | ||
101 | |||
102 | ✗ | static void magicyuv_median_pred16(uint16_t *dst, const uint16_t *src1, | |
103 | const uint16_t *diff, intptr_t w, | ||
104 | int *left, int *left_top, int max) | ||
105 | { | ||
106 | int i; | ||
107 | uint16_t l, lt; | ||
108 | |||
109 | ✗ | l = *left; | |
110 | ✗ | lt = *left_top; | |
111 | |||
112 | ✗ | for (i = 0; i < w; i++) { | |
113 | ✗ | l = mid_pred(l, src1[i], (l + src1[i] - lt)) + diff[i]; | |
114 | ✗ | l &= max; | |
115 | ✗ | lt = src1[i]; | |
116 | ✗ | dst[i] = l; | |
117 | } | ||
118 | |||
119 | ✗ | *left = l; | |
120 | ✗ | *left_top = lt; | |
121 | ✗ | } | |
122 | |||
123 | #define READ_PLANE(dst, plane, b, c) \ | ||
124 | { \ | ||
125 | x = 0; \ | ||
126 | for (; CACHED_BITSTREAM_READER && x < width-c && get_bits_left(&gb) > 0;) {\ | ||
127 | ret = get_vlc_multi(&gb, (uint8_t *)dst + x * b, multi, \ | ||
128 | vlc, vlc_bits, 3, b); \ | ||
129 | if (ret <= 0) \ | ||
130 | return AVERROR_INVALIDDATA; \ | ||
131 | x += ret; \ | ||
132 | } \ | ||
133 | for (; x < width && get_bits_left(&gb) > 0; x++) \ | ||
134 | dst[x] = get_vlc2(&gb, vlc, vlc_bits, 3); \ | ||
135 | dst += stride; \ | ||
136 | } | ||
137 | |||
138 | ✗ | static int magy_decode_slice10(AVCodecContext *avctx, void *tdata, | |
139 | int j, int threadnr) | ||
140 | { | ||
141 | ✗ | const MagicYUVContext *s = avctx->priv_data; | |
142 | ✗ | int interlaced = s->interlaced; | |
143 | ✗ | const int bps = s->bps; | |
144 | ✗ | const int max = s->max - 1; | |
145 | ✗ | AVFrame *p = s->p; | |
146 | int i, k, x; | ||
147 | GetBitContext gb; | ||
148 | uint16_t *dst; | ||
149 | |||
150 | ✗ | for (i = 0; i < s->planes; i++) { | |
151 | int left, lefttop, top; | ||
152 | ✗ | int height = AV_CEIL_RSHIFT(FFMIN(s->slice_height, avctx->coded_height - j * s->slice_height), s->vshift[i]); | |
153 | ✗ | int width = AV_CEIL_RSHIFT(avctx->coded_width, s->hshift[i]); | |
154 | ✗ | int sheight = AV_CEIL_RSHIFT(s->slice_height, s->vshift[i]); | |
155 | ✗ | ptrdiff_t fake_stride = (p->linesize[i] / 2) * (1 + interlaced); | |
156 | ✗ | ptrdiff_t stride = p->linesize[i] / 2; | |
157 | ✗ | const VLC_MULTI_ELEM *const multi = s->multi[i].table; | |
158 | ✗ | const VLCElem *const vlc = s->vlc[i].table; | |
159 | ✗ | const int vlc_bits = s->vlc[i].bits; | |
160 | int flags, pred; | ||
161 | ✗ | int ret = init_get_bits8(&gb, s->buf + s->slices[i][j].start, | |
162 | ✗ | s->slices[i][j].size); | |
163 | |||
164 | ✗ | if (ret < 0) | |
165 | ✗ | return ret; | |
166 | |||
167 | ✗ | flags = get_bits(&gb, 8); | |
168 | ✗ | pred = get_bits(&gb, 8); | |
169 | |||
170 | ✗ | dst = (uint16_t *)p->data[i] + j * sheight * stride; | |
171 | ✗ | if (flags & 1) { | |
172 | ✗ | if (get_bits_left(&gb) < bps * width * height) | |
173 | ✗ | return AVERROR_INVALIDDATA; | |
174 | ✗ | for (k = 0; k < height; k++) { | |
175 | ✗ | for (x = 0; x < width; x++) | |
176 | ✗ | dst[x] = get_bits(&gb, bps); | |
177 | |||
178 | ✗ | dst += stride; | |
179 | } | ||
180 | } else { | ||
181 | ✗ | for (k = 0; k < height; k++) | |
182 | ✗ | READ_PLANE(dst, i, 2, 3) | |
183 | } | ||
184 | |||
185 | ✗ | switch (pred) { | |
186 | ✗ | case LEFT: | |
187 | ✗ | dst = (uint16_t *)p->data[i] + j * sheight * stride; | |
188 | ✗ | s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0); | |
189 | ✗ | dst += stride; | |
190 | ✗ | if (interlaced) { | |
191 | ✗ | s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0); | |
192 | ✗ | dst += stride; | |
193 | } | ||
194 | ✗ | for (k = 1 + interlaced; k < height; k++) { | |
195 | ✗ | s->llviddsp.add_left_pred_int16(dst, dst, max, width, dst[-fake_stride]); | |
196 | ✗ | dst += stride; | |
197 | } | ||
198 | ✗ | break; | |
199 | ✗ | case GRADIENT: | |
200 | ✗ | dst = (uint16_t *)p->data[i] + j * sheight * stride; | |
201 | ✗ | s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0); | |
202 | ✗ | dst += stride; | |
203 | ✗ | if (interlaced) { | |
204 | ✗ | s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0); | |
205 | ✗ | dst += stride; | |
206 | } | ||
207 | ✗ | for (k = 1 + interlaced; k < height; k++) { | |
208 | ✗ | top = dst[-fake_stride]; | |
209 | ✗ | left = top + dst[0]; | |
210 | ✗ | dst[0] = left & max; | |
211 | ✗ | for (x = 1; x < width; x++) { | |
212 | ✗ | top = dst[x - fake_stride]; | |
213 | ✗ | lefttop = dst[x - (fake_stride + 1)]; | |
214 | ✗ | left += top - lefttop + dst[x]; | |
215 | ✗ | dst[x] = left & max; | |
216 | } | ||
217 | ✗ | dst += stride; | |
218 | } | ||
219 | ✗ | break; | |
220 | ✗ | case MEDIAN: | |
221 | ✗ | dst = (uint16_t *)p->data[i] + j * sheight * stride; | |
222 | ✗ | s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0); | |
223 | ✗ | dst += stride; | |
224 | ✗ | if (interlaced) { | |
225 | ✗ | s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0); | |
226 | ✗ | dst += stride; | |
227 | } | ||
228 | ✗ | lefttop = left = dst[0]; | |
229 | ✗ | for (k = 1 + interlaced; k < height; k++) { | |
230 | ✗ | magicyuv_median_pred16(dst, dst - fake_stride, dst, width, &left, &lefttop, max); | |
231 | ✗ | lefttop = left = dst[0]; | |
232 | ✗ | dst += stride; | |
233 | } | ||
234 | ✗ | break; | |
235 | ✗ | default: | |
236 | ✗ | avpriv_request_sample(avctx, "Unknown prediction: %d", pred); | |
237 | } | ||
238 | } | ||
239 | |||
240 | ✗ | if (s->decorrelate) { | |
241 | ✗ | int height = FFMIN(s->slice_height, avctx->coded_height - j * s->slice_height); | |
242 | ✗ | int width = avctx->coded_width; | |
243 | ✗ | uint16_t *r = (uint16_t *)p->data[0] + j * s->slice_height * p->linesize[0] / 2; | |
244 | ✗ | uint16_t *g = (uint16_t *)p->data[1] + j * s->slice_height * p->linesize[1] / 2; | |
245 | ✗ | uint16_t *b = (uint16_t *)p->data[2] + j * s->slice_height * p->linesize[2] / 2; | |
246 | |||
247 | ✗ | for (i = 0; i < height; i++) { | |
248 | ✗ | for (k = 0; k < width; k++) { | |
249 | ✗ | b[k] = (b[k] + g[k]) & max; | |
250 | ✗ | r[k] = (r[k] + g[k]) & max; | |
251 | } | ||
252 | ✗ | b += p->linesize[0] / 2; | |
253 | ✗ | g += p->linesize[1] / 2; | |
254 | ✗ | r += p->linesize[2] / 2; | |
255 | } | ||
256 | } | ||
257 | |||
258 | ✗ | return 0; | |
259 | } | ||
260 | |||
261 | 126 | static int magy_decode_slice(AVCodecContext *avctx, void *tdata, | |
262 | int j, int threadnr) | ||
263 | { | ||
264 | 126 | const MagicYUVContext *s = avctx->priv_data; | |
265 | 126 | int interlaced = s->interlaced; | |
266 | 126 | AVFrame *p = s->p; | |
267 | int i, k, x, min_width; | ||
268 | GetBitContext gb; | ||
269 | uint8_t *dst; | ||
270 | |||
271 |
2/2✓ Branch 0 taken 378 times.
✓ Branch 1 taken 126 times.
|
504 | for (i = 0; i < s->planes; i++) { |
272 | int left, lefttop, top; | ||
273 | 378 | int height = AV_CEIL_RSHIFT(FFMIN(s->slice_height, avctx->coded_height - j * s->slice_height), s->vshift[i]); | |
274 | 378 | int width = AV_CEIL_RSHIFT(avctx->coded_width, s->hshift[i]); | |
275 | 378 | int sheight = AV_CEIL_RSHIFT(s->slice_height, s->vshift[i]); | |
276 | 378 | ptrdiff_t fake_stride = p->linesize[i] * (1 + interlaced); | |
277 | 378 | ptrdiff_t stride = p->linesize[i]; | |
278 | 378 | const uint8_t *slice = s->buf + s->slices[i][j].start; | |
279 | 378 | const VLC_MULTI_ELEM *const multi = s->multi[i].table; | |
280 | 378 | const VLCElem *const vlc = s->vlc[i].table; | |
281 | 378 | const int vlc_bits = s->vlc[i].bits; | |
282 | int flags, pred; | ||
283 | |||
284 | 378 | flags = bytestream_get_byte(&slice); | |
285 | 378 | pred = bytestream_get_byte(&slice); | |
286 | |||
287 | 378 | dst = p->data[i] + j * sheight * stride; | |
288 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 378 times.
|
378 | if (flags & 1) { |
289 | ✗ | if (s->slices[i][j].size - 2 < width * height) | |
290 | ✗ | return AVERROR_INVALIDDATA; | |
291 | ✗ | for (k = 0; k < height; k++) { | |
292 | ✗ | bytestream_get_buffer(&slice, dst, width); | |
293 | ✗ | dst += stride; | |
294 | } | ||
295 | } else { | ||
296 | 378 | int ret = init_get_bits8(&gb, slice, s->slices[i][j].size - 2); | |
297 | |||
298 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 378 times.
|
378 | if (ret < 0) |
299 | ✗ | return ret; | |
300 | |||
301 |
2/2✓ Branch 0 taken 9280 times.
✓ Branch 1 taken 378 times.
|
9658 | for (k = 0; k < height; k++) |
302 |
7/10✗ Branch 1 not taken.
✓ Branch 2 taken 654778 times.
✓ Branch 3 taken 654778 times.
✓ Branch 4 taken 9280 times.
✓ Branch 6 taken 654778 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 52724 times.
✓ Branch 10 taken 9280 times.
✓ Branch 12 taken 52724 times.
✗ Branch 13 not taken.
|
716782 | READ_PLANE(dst, i, 1, 7) |
303 | } | ||
304 | |||
305 |
3/4✓ Branch 0 taken 126 times.
✓ Branch 1 taken 90 times.
✓ Branch 2 taken 162 times.
✗ Branch 3 not taken.
|
378 | switch (pred) { |
306 | 126 | case LEFT: | |
307 | 126 | dst = p->data[i] + j * sheight * stride; | |
308 | 126 | s->llviddsp.add_left_pred(dst, dst, width, 0); | |
309 | 126 | dst += stride; | |
310 |
2/2✓ Branch 0 taken 72 times.
✓ Branch 1 taken 54 times.
|
126 | if (interlaced) { |
311 | 72 | s->llviddsp.add_left_pred(dst, dst, width, 0); | |
312 | 72 | dst += stride; | |
313 | } | ||
314 |
2/2✓ Branch 0 taken 3050 times.
✓ Branch 1 taken 126 times.
|
3176 | for (k = 1 + interlaced; k < height; k++) { |
315 | 3050 | s->llviddsp.add_left_pred(dst, dst, width, dst[-fake_stride]); | |
316 | 3050 | dst += stride; | |
317 | } | ||
318 | 126 | break; | |
319 | 90 | case GRADIENT: | |
320 | 90 | dst = p->data[i] + j * sheight * stride; | |
321 | 90 | s->llviddsp.add_left_pred(dst, dst, width, 0); | |
322 | 90 | dst += stride; | |
323 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 72 times.
|
90 | if (interlaced) { |
324 | 18 | s->llviddsp.add_left_pred(dst, dst, width, 0); | |
325 | 18 | dst += stride; | |
326 | } | ||
327 | 90 | min_width = FFMIN(width, 32); | |
328 |
2/2✓ Branch 0 taken 2212 times.
✓ Branch 1 taken 90 times.
|
2302 | for (k = 1 + interlaced; k < height; k++) { |
329 | 2212 | top = dst[-fake_stride]; | |
330 | 2212 | left = top + dst[0]; | |
331 | 2212 | dst[0] = left; | |
332 |
2/2✓ Branch 0 taken 68572 times.
✓ Branch 1 taken 2212 times.
|
70784 | for (x = 1; x < min_width; x++) { /* dsp need aligned 32 */ |
333 | 68572 | top = dst[x - fake_stride]; | |
334 | 68572 | lefttop = dst[x - (fake_stride + 1)]; | |
335 | 68572 | left += top - lefttop + dst[x]; | |
336 | 68572 | dst[x] = left; | |
337 | } | ||
338 |
1/2✓ Branch 0 taken 2212 times.
✗ Branch 1 not taken.
|
2212 | if (width > 32) |
339 | 2212 | s->llviddsp.add_gradient_pred(dst + 32, fake_stride, width - 32); | |
340 | 2212 | dst += stride; | |
341 | } | ||
342 | 90 | break; | |
343 | 162 | case MEDIAN: | |
344 | 162 | dst = p->data[i] + j * sheight * stride; | |
345 | 162 | s->llviddsp.add_left_pred(dst, dst, width, 0); | |
346 | 162 | dst += stride; | |
347 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 108 times.
|
162 | if (interlaced) { |
348 | 54 | s->llviddsp.add_left_pred(dst, dst, width, 0); | |
349 | 54 | dst += stride; | |
350 | } | ||
351 | 162 | lefttop = left = dst[0]; | |
352 |
2/2✓ Branch 0 taken 3496 times.
✓ Branch 1 taken 162 times.
|
3658 | for (k = 1 + interlaced; k < height; k++) { |
353 | 3496 | s->llviddsp.add_median_pred(dst, dst - fake_stride, | |
354 | dst, width, &left, &lefttop); | ||
355 | 3496 | lefttop = left = dst[0]; | |
356 | 3496 | dst += stride; | |
357 | } | ||
358 | 162 | break; | |
359 | ✗ | default: | |
360 | ✗ | avpriv_request_sample(avctx, "Unknown prediction: %d", pred); | |
361 | } | ||
362 | } | ||
363 | |||
364 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 90 times.
|
126 | if (s->decorrelate) { |
365 | 36 | int height = FFMIN(s->slice_height, avctx->coded_height - j * s->slice_height); | |
366 | 36 | int width = avctx->coded_width; | |
367 | 36 | uint8_t *b = p->data[0] + j * s->slice_height * p->linesize[0]; | |
368 | 36 | uint8_t *g = p->data[1] + j * s->slice_height * p->linesize[1]; | |
369 | 36 | uint8_t *r = p->data[2] + j * s->slice_height * p->linesize[2]; | |
370 | |||
371 |
2/2✓ Branch 0 taken 928 times.
✓ Branch 1 taken 36 times.
|
964 | for (i = 0; i < height; i++) { |
372 | 928 | s->llviddsp.add_bytes(b, g, width); | |
373 | 928 | s->llviddsp.add_bytes(r, g, width); | |
374 | 928 | b += p->linesize[0]; | |
375 | 928 | g += p->linesize[1]; | |
376 | 928 | r += p->linesize[2]; | |
377 | } | ||
378 | } | ||
379 | |||
380 | 126 | return 0; | |
381 | } | ||
382 | |||
383 | 14 | static int build_huffman(AVCodecContext *avctx, const uint8_t *table, | |
384 | int table_size, int max) | ||
385 | { | ||
386 | 14 | MagicYUVContext *s = avctx->priv_data; | |
387 | GetByteContext gb; | ||
388 | 14 | uint8_t *len = s->len; | |
389 | 14 | uint16_t length_count[33] = { 0 }; | |
390 | 14 | int i = 0, j = 0, k; | |
391 | |||
392 | 14 | bytestream2_init(&gb, table, table_size); | |
393 | |||
394 |
1/2✓ Branch 1 taken 1036 times.
✗ Branch 2 not taken.
|
1050 | while (bytestream2_get_bytes_left(&gb) > 0) { |
395 | 1036 | int b = bytestream2_peek_byteu(&gb) & 0x80; | |
396 | 1036 | int x = bytestream2_get_byteu(&gb) & ~0x80; | |
397 | 1036 | int l = 1; | |
398 | |||
399 |
2/2✓ Branch 0 taken 424 times.
✓ Branch 1 taken 612 times.
|
1036 | if (b) { |
400 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 424 times.
|
424 | if (bytestream2_get_bytes_left(&gb) <= 0) |
401 | ✗ | break; | |
402 | 424 | l += bytestream2_get_byteu(&gb); | |
403 | } | ||
404 | 1036 | k = j + l; | |
405 |
3/6✓ Branch 0 taken 1036 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1036 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1036 times.
|
1036 | if (k > max || x == 0 || x > 32) { |
406 | ✗ | av_log(avctx, AV_LOG_ERROR, "Invalid Huffman codes\n"); | |
407 | ✗ | return AVERROR_INVALIDDATA; | |
408 | } | ||
409 | |||
410 | 1036 | length_count[x] += l; | |
411 |
2/2✓ Branch 0 taken 10752 times.
✓ Branch 1 taken 1036 times.
|
11788 | for (; j < k; j++) |
412 | 10752 | len[j] = x; | |
413 | |||
414 |
2/2✓ Branch 0 taken 994 times.
✓ Branch 1 taken 42 times.
|
1036 | if (j == max) { |
415 | 42 | j = 0; | |
416 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
|
42 | if (huff_build(avctx, len, length_count, &s->vlc[i], &s->multi[i], max, avctx)) { |
417 | ✗ | av_log(avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n"); | |
418 | ✗ | return AVERROR_INVALIDDATA; | |
419 | } | ||
420 | 42 | i++; | |
421 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 28 times.
|
42 | if (i == s->planes) { |
422 | 14 | break; | |
423 | } | ||
424 | 28 | memset(length_count, 0, sizeof(length_count)); | |
425 | } | ||
426 | } | ||
427 | |||
428 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (i != s->planes) { |
429 | ✗ | av_log(avctx, AV_LOG_ERROR, "Huffman tables too short\n"); | |
430 | ✗ | return AVERROR_INVALIDDATA; | |
431 | } | ||
432 | |||
433 | 14 | return 0; | |
434 | } | ||
435 | |||
436 | 14 | static int magy_decode_frame(AVCodecContext *avctx, AVFrame *p, | |
437 | int *got_frame, AVPacket *avpkt) | ||
438 | { | ||
439 | 14 | MagicYUVContext *s = avctx->priv_data; | |
440 | GetByteContext gb; | ||
441 | uint32_t first_offset, offset, next_offset, header_size, slice_width; | ||
442 | int width, height, format, version, table_size; | ||
443 | int ret, i, j; | ||
444 | |||
445 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (avpkt->size < 36) |
446 | ✗ | return AVERROR_INVALIDDATA; | |
447 | |||
448 | 14 | bytestream2_init(&gb, avpkt->data, avpkt->size); | |
449 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
|
14 | if (bytestream2_get_le32u(&gb) != MKTAG('M', 'A', 'G', 'Y')) |
450 | ✗ | return AVERROR_INVALIDDATA; | |
451 | |||
452 | 14 | header_size = bytestream2_get_le32u(&gb); | |
453 |
2/4✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
|
14 | if (header_size < 32 || header_size >= avpkt->size) { |
454 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
455 | "header or packet too small %"PRIu32"\n", header_size); | ||
456 | ✗ | return AVERROR_INVALIDDATA; | |
457 | } | ||
458 | |||
459 | 14 | version = bytestream2_get_byteu(&gb); | |
460 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (version != 7) { |
461 | ✗ | avpriv_request_sample(avctx, "Version %d", version); | |
462 | ✗ | return AVERROR_PATCHWELCOME; | |
463 | } | ||
464 | |||
465 | 14 | s->hshift[1] = | |
466 | 14 | s->vshift[1] = | |
467 | 14 | s->hshift[2] = | |
468 | 14 | s->vshift[2] = 0; | |
469 | 14 | s->decorrelate = 0; | |
470 | 14 | s->bps = 8; | |
471 | |||
472 | 14 | format = bytestream2_get_byteu(&gb); | |
473 |
7/18✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
|
14 | switch (format) { |
474 | 2 | case 0x65: | |
475 | 2 | avctx->pix_fmt = AV_PIX_FMT_GBRP; | |
476 | 2 | s->decorrelate = 1; | |
477 | 2 | break; | |
478 | 2 | case 0x66: | |
479 | 2 | avctx->pix_fmt = AV_PIX_FMT_GBRAP; | |
480 | 2 | s->decorrelate = 1; | |
481 | 2 | break; | |
482 | 2 | case 0x67: | |
483 | 2 | avctx->pix_fmt = AV_PIX_FMT_YUV444P; | |
484 | 2 | break; | |
485 | 2 | case 0x68: | |
486 | 2 | avctx->pix_fmt = AV_PIX_FMT_YUV422P; | |
487 | 2 | s->hshift[1] = | |
488 | 2 | s->hshift[2] = 1; | |
489 | 2 | break; | |
490 | 2 | case 0x69: | |
491 | 2 | avctx->pix_fmt = AV_PIX_FMT_YUV420P; | |
492 | 2 | s->hshift[1] = | |
493 | 2 | s->vshift[1] = | |
494 | 2 | s->hshift[2] = | |
495 | 2 | s->vshift[2] = 1; | |
496 | 2 | break; | |
497 | 2 | case 0x6a: | |
498 | 2 | avctx->pix_fmt = AV_PIX_FMT_YUVA444P; | |
499 | 2 | break; | |
500 | 2 | case 0x6b: | |
501 | 2 | avctx->pix_fmt = AV_PIX_FMT_GRAY8; | |
502 | 2 | break; | |
503 | ✗ | case 0x6c: | |
504 | ✗ | avctx->pix_fmt = AV_PIX_FMT_YUV422P10; | |
505 | ✗ | s->hshift[1] = | |
506 | ✗ | s->hshift[2] = 1; | |
507 | ✗ | s->bps = 10; | |
508 | ✗ | break; | |
509 | ✗ | case 0x76: | |
510 | ✗ | avctx->pix_fmt = AV_PIX_FMT_YUV444P10; | |
511 | ✗ | s->bps = 10; | |
512 | ✗ | break; | |
513 | ✗ | case 0x6d: | |
514 | ✗ | avctx->pix_fmt = AV_PIX_FMT_GBRP10; | |
515 | ✗ | s->decorrelate = 1; | |
516 | ✗ | s->bps = 10; | |
517 | ✗ | break; | |
518 | ✗ | case 0x6e: | |
519 | ✗ | avctx->pix_fmt = AV_PIX_FMT_GBRAP10; | |
520 | ✗ | s->decorrelate = 1; | |
521 | ✗ | s->bps = 10; | |
522 | ✗ | break; | |
523 | ✗ | case 0x6f: | |
524 | ✗ | avctx->pix_fmt = AV_PIX_FMT_GBRP12; | |
525 | ✗ | s->decorrelate = 1; | |
526 | ✗ | s->bps = 12; | |
527 | ✗ | break; | |
528 | ✗ | case 0x70: | |
529 | ✗ | avctx->pix_fmt = AV_PIX_FMT_GBRAP12; | |
530 | ✗ | s->decorrelate = 1; | |
531 | ✗ | s->bps = 12; | |
532 | ✗ | break; | |
533 | ✗ | case 0x71: | |
534 | ✗ | avctx->pix_fmt = AV_PIX_FMT_GBRP14; | |
535 | ✗ | s->decorrelate = 1; | |
536 | ✗ | s->bps = 14; | |
537 | ✗ | break; | |
538 | ✗ | case 0x72: | |
539 | ✗ | avctx->pix_fmt = AV_PIX_FMT_GBRAP14; | |
540 | ✗ | s->decorrelate = 1; | |
541 | ✗ | s->bps = 14; | |
542 | ✗ | break; | |
543 | ✗ | case 0x73: | |
544 | ✗ | avctx->pix_fmt = AV_PIX_FMT_GRAY10; | |
545 | ✗ | s->bps = 10; | |
546 | ✗ | break; | |
547 | ✗ | case 0x7b: | |
548 | ✗ | avctx->pix_fmt = AV_PIX_FMT_YUV420P10; | |
549 | ✗ | s->hshift[1] = | |
550 | ✗ | s->vshift[1] = | |
551 | ✗ | s->hshift[2] = | |
552 | ✗ | s->vshift[2] = 1; | |
553 | ✗ | s->bps = 10; | |
554 | ✗ | break; | |
555 | ✗ | default: | |
556 | ✗ | avpriv_request_sample(avctx, "Format 0x%X", format); | |
557 | ✗ | return AVERROR_PATCHWELCOME; | |
558 | } | ||
559 | 14 | s->max = 1 << s->bps; | |
560 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | s->magy_decode_slice = s->bps == 8 ? magy_decode_slice : magy_decode_slice10; |
561 | 14 | s->planes = av_pix_fmt_count_planes(avctx->pix_fmt); | |
562 | |||
563 | 14 | bytestream2_skipu(&gb, 1); | |
564 | 14 | s->color_matrix = bytestream2_get_byteu(&gb); | |
565 | 14 | s->flags = bytestream2_get_byteu(&gb); | |
566 | 14 | s->interlaced = !!(s->flags & 2); | |
567 | 14 | bytestream2_skipu(&gb, 3); | |
568 | |||
569 | 14 | width = bytestream2_get_le32u(&gb); | |
570 | 14 | height = bytestream2_get_le32u(&gb); | |
571 | 14 | ret = ff_set_dimensions(avctx, width, height); | |
572 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (ret < 0) |
573 | ✗ | return ret; | |
574 | |||
575 | 14 | slice_width = bytestream2_get_le32u(&gb); | |
576 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (slice_width != avctx->coded_width) { |
577 | ✗ | avpriv_request_sample(avctx, "Slice width %"PRIu32, slice_width); | |
578 | ✗ | return AVERROR_PATCHWELCOME; | |
579 | } | ||
580 | 14 | s->slice_height = bytestream2_get_le32u(&gb); | |
581 |
2/4✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
|
14 | if (s->slice_height <= 0 || s->slice_height > INT_MAX - avctx->coded_height) { |
582 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
583 | "invalid slice height: %d\n", s->slice_height); | ||
584 | ✗ | return AVERROR_INVALIDDATA; | |
585 | } | ||
586 | |||
587 | 14 | bytestream2_skipu(&gb, 4); | |
588 | |||
589 | 14 | s->nb_slices = (avctx->coded_height + s->slice_height - 1) / s->slice_height; | |
590 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (s->nb_slices > INT_MAX / FFMAX(sizeof(Slice), 4 * 5)) { |
591 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
592 | "invalid number of slices: %d\n", s->nb_slices); | ||
593 | ✗ | return AVERROR_INVALIDDATA; | |
594 | } | ||
595 | |||
596 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
|
14 | if (s->interlaced) { |
597 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if ((s->slice_height >> s->vshift[1]) < 2) { |
598 | ✗ | av_log(avctx, AV_LOG_ERROR, "impossible slice height\n"); | |
599 | ✗ | return AVERROR_INVALIDDATA; | |
600 | } | ||
601 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
|
6 | if ((avctx->coded_height % s->slice_height) && ((avctx->coded_height % s->slice_height) >> s->vshift[1]) < 2) { |
602 | ✗ | av_log(avctx, AV_LOG_ERROR, "impossible height\n"); | |
603 | ✗ | return AVERROR_INVALIDDATA; | |
604 | } | ||
605 | } | ||
606 | |||
607 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
|
14 | if (bytestream2_get_bytes_left(&gb) <= s->nb_slices * s->planes * 5) |
608 | ✗ | return AVERROR_INVALIDDATA; | |
609 |
2/2✓ Branch 0 taken 42 times.
✓ Branch 1 taken 14 times.
|
56 | for (i = 0; i < s->planes; i++) { |
610 | 42 | av_fast_malloc(&s->slices[i], &s->slices_size[i], s->nb_slices * sizeof(Slice)); | |
611 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
|
42 | if (!s->slices[i]) |
612 | ✗ | return AVERROR(ENOMEM); | |
613 | |||
614 | 42 | offset = bytestream2_get_le32u(&gb); | |
615 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
|
42 | if (offset >= avpkt->size - header_size) |
616 | ✗ | return AVERROR_INVALIDDATA; | |
617 | |||
618 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 28 times.
|
42 | if (i == 0) |
619 | 14 | first_offset = offset; | |
620 | |||
621 |
2/2✓ Branch 0 taken 336 times.
✓ Branch 1 taken 42 times.
|
378 | for (j = 0; j < s->nb_slices - 1; j++) { |
622 | 336 | s->slices[i][j].start = offset + header_size; | |
623 | |||
624 | 336 | next_offset = bytestream2_get_le32u(&gb); | |
625 |
2/4✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 336 times.
|
336 | if (next_offset <= offset || next_offset >= avpkt->size - header_size) |
626 | ✗ | return AVERROR_INVALIDDATA; | |
627 | |||
628 | 336 | s->slices[i][j].size = next_offset - offset; | |
629 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
|
336 | if (s->slices[i][j].size < 2) |
630 | ✗ | return AVERROR_INVALIDDATA; | |
631 | 336 | offset = next_offset; | |
632 | } | ||
633 | |||
634 | 42 | s->slices[i][j].start = offset + header_size; | |
635 | 42 | s->slices[i][j].size = avpkt->size - s->slices[i][j].start; | |
636 | |||
637 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
|
42 | if (s->slices[i][j].size < 2) |
638 | ✗ | return AVERROR_INVALIDDATA; | |
639 | } | ||
640 | |||
641 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
|
14 | if (bytestream2_get_byteu(&gb) != s->planes) |
642 | ✗ | return AVERROR_INVALIDDATA; | |
643 | |||
644 | 14 | bytestream2_skipu(&gb, s->nb_slices * s->planes); | |
645 | |||
646 | 14 | table_size = header_size + first_offset - bytestream2_tell(&gb); | |
647 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (table_size < 2) |
648 | ✗ | return AVERROR_INVALIDDATA; | |
649 | |||
650 | 14 | ret = build_huffman(avctx, avpkt->data + bytestream2_tell(&gb), | |
651 | table_size, s->max); | ||
652 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (ret < 0) |
653 | ✗ | return ret; | |
654 | |||
655 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
|
14 | if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) |
656 | ✗ | return ret; | |
657 | |||
658 | 14 | s->buf = avpkt->data; | |
659 | 14 | s->p = p; | |
660 | 14 | avctx->execute2(avctx, s->magy_decode_slice, NULL, NULL, s->nb_slices); | |
661 | |||
662 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 2 times.
|
14 | if (avctx->pix_fmt == AV_PIX_FMT_GBRP || |
663 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
|
12 | avctx->pix_fmt == AV_PIX_FMT_GBRAP || |
664 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | avctx->pix_fmt == AV_PIX_FMT_GBRP10 || |
665 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | avctx->pix_fmt == AV_PIX_FMT_GBRAP10|| |
666 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | avctx->pix_fmt == AV_PIX_FMT_GBRAP12|| |
667 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | avctx->pix_fmt == AV_PIX_FMT_GBRAP14|| |
668 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | avctx->pix_fmt == AV_PIX_FMT_GBRP12|| |
669 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | avctx->pix_fmt == AV_PIX_FMT_GBRP14) { |
670 | 4 | FFSWAP(uint8_t*, p->data[0], p->data[1]); | |
671 | 4 | FFSWAP(int, p->linesize[0], p->linesize[1]); | |
672 | } else { | ||
673 |
1/3✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | switch (s->color_matrix) { |
674 | ✗ | case 1: | |
675 | ✗ | p->colorspace = AVCOL_SPC_BT470BG; | |
676 | ✗ | break; | |
677 | 10 | case 2: | |
678 | 10 | p->colorspace = AVCOL_SPC_BT709; | |
679 | 10 | break; | |
680 | } | ||
681 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
|
10 | p->color_range = (s->flags & 4) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; |
682 | } | ||
683 | |||
684 | 14 | *got_frame = 1; | |
685 | |||
686 | 14 | return avpkt->size; | |
687 | } | ||
688 | |||
689 | 14 | static av_cold int magy_decode_init(AVCodecContext *avctx) | |
690 | { | ||
691 | 14 | MagicYUVContext *s = avctx->priv_data; | |
692 | 14 | ff_llviddsp_init(&s->llviddsp); | |
693 | 14 | return 0; | |
694 | } | ||
695 | |||
696 | 14 | static av_cold int magy_decode_end(AVCodecContext *avctx) | |
697 | { | ||
698 | 14 | MagicYUVContext * const s = avctx->priv_data; | |
699 | int i; | ||
700 | |||
701 |
2/2✓ Branch 0 taken 56 times.
✓ Branch 1 taken 14 times.
|
70 | for (i = 0; i < FF_ARRAY_ELEMS(s->slices); i++) { |
702 | 56 | av_freep(&s->slices[i]); | |
703 | 56 | s->slices_size[i] = 0; | |
704 | 56 | ff_vlc_free(&s->vlc[i]); | |
705 | 56 | ff_vlc_free_multi(&s->multi[i]); | |
706 | } | ||
707 | |||
708 | 14 | return 0; | |
709 | } | ||
710 | |||
711 | const FFCodec ff_magicyuv_decoder = { | ||
712 | .p.name = "magicyuv", | ||
713 | CODEC_LONG_NAME("MagicYUV video"), | ||
714 | .p.type = AVMEDIA_TYPE_VIDEO, | ||
715 | .p.id = AV_CODEC_ID_MAGICYUV, | ||
716 | .priv_data_size = sizeof(MagicYUVContext), | ||
717 | .init = magy_decode_init, | ||
718 | .close = magy_decode_end, | ||
719 | FF_CODEC_DECODE_CB(magy_decode_frame), | ||
720 | .p.capabilities = AV_CODEC_CAP_DR1 | | ||
721 | AV_CODEC_CAP_FRAME_THREADS | | ||
722 | AV_CODEC_CAP_SLICE_THREADS, | ||
723 | }; | ||
724 |