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