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