/src/ffmpeg/libavcodec/magicyuv.c
Line | Count | 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 | 384M | #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 | | 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 | 46.7k | { |
85 | 46.7k | MagicYUVContext *s = avctx->priv_data; |
86 | 46.7k | HuffEntry *he = s->he; |
87 | | |
88 | 1.49M | for (int i = 31; i > 0; i--) |
89 | 1.44M | codes_pos[i] += codes_pos[i + 1]; |
90 | | |
91 | 30.6M | for (unsigned i = nb_elems; i-- > 0;) |
92 | 30.5M | he[--codes_pos[len[i]]] = (HuffEntry){ len[i], i }; |
93 | | |
94 | 46.7k | ff_vlc_free(vlc); |
95 | 46.7k | ff_vlc_free_multi(multi); |
96 | 46.7k | return ff_vlc_init_multi_from_lengths(vlc, multi, FFMIN(he[0].len, VLC_BITS), nb_elems, nb_elems, |
97 | 46.7k | &he[0].len, sizeof(he[0]), |
98 | 46.7k | &he[0].sym, sizeof(he[0]), sizeof(he[0].sym), |
99 | 46.7k | 0, 0, logctx); |
100 | 46.7k | } |
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 | 5.83M | { |
106 | 5.83M | int i; |
107 | 5.83M | uint16_t l, lt; |
108 | | |
109 | 5.83M | l = *left; |
110 | 5.83M | lt = *left_top; |
111 | | |
112 | 332M | for (i = 0; i < w; i++) { |
113 | 326M | l = mid_pred(l, src1[i], (l + src1[i] - lt)) + diff[i]; |
114 | 326M | l &= max; |
115 | 326M | lt = src1[i]; |
116 | 326M | dst[i] = l; |
117 | 326M | } |
118 | | |
119 | 5.83M | *left = l; |
120 | 5.83M | *left_top = lt; |
121 | 5.83M | } |
122 | | |
123 | 191M | #define READ_PLANE(dst, plane, b, c) \ |
124 | 191M | { \ |
125 | 191M | x = 0; \ |
126 | 192M | for (; CACHED_BITSTREAM_READER && x < width-c && get_bits_left(&gb) > 0;) {\ |
127 | 490k | ret = get_vlc_multi(&gb, (uint8_t *)dst + x * b, multi, \ |
128 | 490k | vlc, vlc_bits, 3, b); \ |
129 | 490k | if (ret <= 0) \ |
130 | 490k | return AVERROR_INVALIDDATA; \ |
131 | 490k | x += ret; \ |
132 | 489k | } \ |
133 | 268M | for (; x < width && get_bits_left(&gb) > 0; x++) \ |
134 | 191M | dst[x] = get_vlc2(&gb, vlc, vlc_bits, 3); \ |
135 | 191M | dst += stride; \ |
136 | 191M | } |
137 | | |
138 | | static int magy_decode_slice10(AVCodecContext *avctx, void *tdata, |
139 | | int j, int threadnr) |
140 | 4.92k | { |
141 | 4.92k | const MagicYUVContext *s = avctx->priv_data; |
142 | 4.92k | int interlaced = s->interlaced; |
143 | 4.92k | const int bps = s->bps; |
144 | 4.92k | const int max = s->max - 1; |
145 | 4.92k | AVFrame *p = s->p; |
146 | 4.92k | int i, k, x; |
147 | 4.92k | GetBitContext gb; |
148 | 4.92k | uint16_t *dst; |
149 | | |
150 | 13.7k | for (i = 0; i < s->planes; i++) { |
151 | 9.96k | int left, lefttop, top; |
152 | 9.96k | int height = AV_CEIL_RSHIFT(FFMIN(s->slice_height, avctx->coded_height - j * s->slice_height), s->vshift[i]); |
153 | 9.96k | int width = AV_CEIL_RSHIFT(avctx->coded_width, s->hshift[i]); |
154 | 9.96k | int sheight = AV_CEIL_RSHIFT(s->slice_height, s->vshift[i]); |
155 | 9.96k | ptrdiff_t fake_stride = (p->linesize[i] / 2) * (1 + interlaced); |
156 | 9.96k | ptrdiff_t stride = p->linesize[i] / 2; |
157 | 9.96k | const VLC_MULTI_ELEM *const multi = s->multi[i].table; |
158 | 9.96k | const VLCElem *const vlc = s->vlc[i].table; |
159 | 9.96k | const int vlc_bits = s->vlc[i].bits; |
160 | 9.96k | int flags, pred; |
161 | 9.96k | int ret = init_get_bits8(&gb, s->buf + s->slices[i][j].start, |
162 | 9.96k | s->slices[i][j].size); |
163 | | |
164 | 9.96k | if (ret < 0) |
165 | 0 | return ret; |
166 | | |
167 | 9.96k | flags = get_bits(&gb, 8); |
168 | 9.96k | pred = get_bits(&gb, 8); |
169 | | |
170 | 9.96k | dst = (uint16_t *)p->data[i] + j * sheight * stride; |
171 | 9.96k | if (flags & 1) { |
172 | 1.15k | if (get_bits_left(&gb) < bps * width * height) |
173 | 407 | return AVERROR_INVALIDDATA; |
174 | 5.42k | for (k = 0; k < height; k++) { |
175 | 55.4k | for (x = 0; x < width; x++) |
176 | 50.7k | dst[x] = get_bits(&gb, bps); |
177 | | |
178 | 4.67k | dst += stride; |
179 | 4.67k | } |
180 | 8.81k | } else { |
181 | 26.7M | for (k = 0; k < height; k++) |
182 | 26.7M | READ_PLANE(dst, i, 2, 3) |
183 | 8.81k | } |
184 | | |
185 | 8.87k | switch (pred) { |
186 | 2.76k | case LEFT: |
187 | 2.76k | dst = (uint16_t *)p->data[i] + j * sheight * stride; |
188 | 2.76k | s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0); |
189 | 2.76k | dst += stride; |
190 | 2.76k | if (interlaced) { |
191 | 711 | s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0); |
192 | 711 | dst += stride; |
193 | 711 | } |
194 | 1.95M | for (k = 1 + interlaced; k < height; k++) { |
195 | 1.94M | s->llviddsp.add_left_pred_int16(dst, dst, max, width, dst[-fake_stride]); |
196 | 1.94M | dst += stride; |
197 | 1.94M | } |
198 | 2.76k | break; |
199 | 776 | case GRADIENT: |
200 | 776 | dst = (uint16_t *)p->data[i] + j * sheight * stride; |
201 | 776 | s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0); |
202 | 776 | dst += stride; |
203 | 776 | if (interlaced) { |
204 | 240 | s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0); |
205 | 240 | dst += stride; |
206 | 240 | } |
207 | 11.7M | for (k = 1 + interlaced; k < height; k++) { |
208 | 11.7M | top = dst[-fake_stride]; |
209 | 11.7M | left = top + dst[0]; |
210 | 11.7M | dst[0] = left & max; |
211 | 202M | for (x = 1; x < width; x++) { |
212 | 190M | top = dst[x - fake_stride]; |
213 | 190M | lefttop = dst[x - (fake_stride + 1)]; |
214 | 190M | left += top - lefttop + dst[x]; |
215 | 190M | dst[x] = left & max; |
216 | 190M | } |
217 | 11.7M | dst += stride; |
218 | 11.7M | } |
219 | 776 | break; |
220 | 771 | case MEDIAN: |
221 | 771 | dst = (uint16_t *)p->data[i] + j * sheight * stride; |
222 | 771 | s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0); |
223 | 771 | dst += stride; |
224 | 771 | if (interlaced) { |
225 | 327 | s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0); |
226 | 327 | dst += stride; |
227 | 327 | } |
228 | 771 | lefttop = left = dst[0]; |
229 | 5.83M | for (k = 1 + interlaced; k < height; k++) { |
230 | 5.83M | magicyuv_median_pred16(dst, dst - fake_stride, dst, width, &left, &lefttop, max); |
231 | 5.83M | lefttop = left = dst[0]; |
232 | 5.83M | dst += stride; |
233 | 5.83M | } |
234 | 771 | break; |
235 | 4.56k | default: |
236 | 4.56k | avpriv_request_sample(avctx, "Unknown prediction: %d", pred); |
237 | 8.87k | } |
238 | 8.87k | } |
239 | | |
240 | 3.83k | if (s->decorrelate) { |
241 | 1.21k | int height = FFMIN(s->slice_height, avctx->coded_height - j * s->slice_height); |
242 | 1.21k | int width = avctx->coded_width; |
243 | 1.21k | uint16_t *r = (uint16_t *)p->data[0] + j * s->slice_height * p->linesize[0] / 2; |
244 | 1.21k | uint16_t *g = (uint16_t *)p->data[1] + j * s->slice_height * p->linesize[1] / 2; |
245 | 1.21k | uint16_t *b = (uint16_t *)p->data[2] + j * s->slice_height * p->linesize[2] / 2; |
246 | | |
247 | 996k | for (i = 0; i < height; i++) { |
248 | 839M | for (k = 0; k < width; k++) { |
249 | 838M | b[k] = (b[k] + g[k]) & max; |
250 | 838M | r[k] = (r[k] + g[k]) & max; |
251 | 838M | } |
252 | 995k | b += p->linesize[0] / 2; |
253 | 995k | g += p->linesize[1] / 2; |
254 | 995k | r += p->linesize[2] / 2; |
255 | 995k | } |
256 | 1.21k | } |
257 | | |
258 | 3.83k | return 0; |
259 | 4.92k | } |
260 | | |
261 | | static int magy_decode_slice(AVCodecContext *avctx, void *tdata, |
262 | | int j, int threadnr) |
263 | 15.9k | { |
264 | 15.9k | const MagicYUVContext *s = avctx->priv_data; |
265 | 15.9k | int interlaced = s->interlaced; |
266 | 15.9k | AVFrame *p = s->p; |
267 | 15.9k | int i, k, x, min_width; |
268 | 15.9k | GetBitContext gb; |
269 | 15.9k | uint8_t *dst; |
270 | | |
271 | 42.2k | for (i = 0; i < s->planes; i++) { |
272 | 30.4k | int left, lefttop, top; |
273 | 30.4k | int height = AV_CEIL_RSHIFT(FFMIN(s->slice_height, avctx->coded_height - j * s->slice_height), s->vshift[i]); |
274 | 30.4k | int width = AV_CEIL_RSHIFT(avctx->coded_width, s->hshift[i]); |
275 | 30.4k | int sheight = AV_CEIL_RSHIFT(s->slice_height, s->vshift[i]); |
276 | 30.4k | ptrdiff_t fake_stride = p->linesize[i] * (1 + interlaced); |
277 | 30.4k | ptrdiff_t stride = p->linesize[i]; |
278 | 30.4k | const uint8_t *slice = s->buf + s->slices[i][j].start; |
279 | 30.4k | const VLC_MULTI_ELEM *const multi = s->multi[i].table; |
280 | 30.4k | const VLCElem *const vlc = s->vlc[i].table; |
281 | 30.4k | const int vlc_bits = s->vlc[i].bits; |
282 | 30.4k | int flags, pred; |
283 | | |
284 | 30.4k | flags = bytestream_get_byte(&slice); |
285 | 30.4k | pred = bytestream_get_byte(&slice); |
286 | | |
287 | 30.4k | dst = p->data[i] + j * sheight * stride; |
288 | 30.4k | if (flags & 1) { |
289 | 11.8k | if (s->slices[i][j].size - 2 < width * height) |
290 | 3.56k | return AVERROR_INVALIDDATA; |
291 | 1.19M | for (k = 0; k < height; k++) { |
292 | 1.18M | bytestream_get_buffer(&slice, dst, width); |
293 | 1.18M | dst += stride; |
294 | 1.18M | } |
295 | 18.5k | } else { |
296 | 18.5k | int ret = init_get_bits8(&gb, slice, s->slices[i][j].size - 2); |
297 | | |
298 | 18.5k | if (ret < 0) |
299 | 0 | return ret; |
300 | | |
301 | 164M | for (k = 0; k < height; k++) |
302 | 164M | READ_PLANE(dst, i, 1, 7) |
303 | 18.5k | } |
304 | | |
305 | 26.3k | switch (pred) { |
306 | 1.27k | case LEFT: |
307 | 1.27k | dst = p->data[i] + j * sheight * stride; |
308 | 1.27k | s->llviddsp.add_left_pred(dst, dst, width, 0); |
309 | 1.27k | dst += stride; |
310 | 1.27k | if (interlaced) { |
311 | 444 | s->llviddsp.add_left_pred(dst, dst, width, 0); |
312 | 444 | dst += stride; |
313 | 444 | } |
314 | 13.9M | for (k = 1 + interlaced; k < height; k++) { |
315 | 13.9M | s->llviddsp.add_left_pred(dst, dst, width, dst[-fake_stride]); |
316 | 13.9M | dst += stride; |
317 | 13.9M | } |
318 | 1.27k | break; |
319 | 7.38k | case GRADIENT: |
320 | 7.38k | dst = p->data[i] + j * sheight * stride; |
321 | 7.38k | s->llviddsp.add_left_pred(dst, dst, width, 0); |
322 | 7.38k | dst += stride; |
323 | 7.38k | if (interlaced) { |
324 | 491 | s->llviddsp.add_left_pred(dst, dst, width, 0); |
325 | 491 | dst += stride; |
326 | 491 | } |
327 | 7.38k | min_width = FFMIN(width, 32); |
328 | 12.9M | for (k = 1 + interlaced; k < height; k++) { |
329 | 12.9M | top = dst[-fake_stride]; |
330 | 12.9M | left = top + dst[0]; |
331 | 12.9M | dst[0] = left; |
332 | 74.8M | for (x = 1; x < min_width; x++) { /* dsp need aligned 32 */ |
333 | 61.9M | top = dst[x - fake_stride]; |
334 | 61.9M | lefttop = dst[x - (fake_stride + 1)]; |
335 | 61.9M | left += top - lefttop + dst[x]; |
336 | 61.9M | dst[x] = left; |
337 | 61.9M | } |
338 | 12.9M | if (width > 32) |
339 | 1.93M | s->llviddsp.add_gradient_pred(dst + 32, fake_stride, width - 32); |
340 | 12.9M | dst += stride; |
341 | 12.9M | } |
342 | 7.38k | break; |
343 | 775 | case MEDIAN: |
344 | 775 | dst = p->data[i] + j * sheight * stride; |
345 | 775 | s->llviddsp.add_left_pred(dst, dst, width, 0); |
346 | 775 | dst += stride; |
347 | 775 | if (interlaced) { |
348 | 462 | s->llviddsp.add_left_pred(dst, dst, width, 0); |
349 | 462 | dst += stride; |
350 | 462 | } |
351 | 775 | if (1 + interlaced < height) |
352 | 538 | lefttop = left = dst[0]; |
353 | 11.3M | for (k = 1 + interlaced; k < height; k++) { |
354 | 11.3M | s->llviddsp.add_median_pred(dst, dst - fake_stride, |
355 | 11.3M | dst, width, &left, &lefttop); |
356 | 11.3M | lefttop = left = dst[0]; |
357 | 11.3M | dst += stride; |
358 | 11.3M | } |
359 | 775 | break; |
360 | 16.8k | default: |
361 | 16.8k | avpriv_request_sample(avctx, "Unknown prediction: %d", pred); |
362 | 26.3k | } |
363 | 26.3k | } |
364 | | |
365 | 11.8k | if (s->decorrelate) { |
366 | 4.03k | int height = FFMIN(s->slice_height, avctx->coded_height - j * s->slice_height); |
367 | 4.03k | int width = avctx->coded_width; |
368 | 4.03k | uint8_t *b = p->data[0] + j * s->slice_height * p->linesize[0]; |
369 | 4.03k | uint8_t *g = p->data[1] + j * s->slice_height * p->linesize[1]; |
370 | 4.03k | uint8_t *r = p->data[2] + j * s->slice_height * p->linesize[2]; |
371 | | |
372 | 1.45M | for (i = 0; i < height; i++) { |
373 | 1.44M | s->llviddsp.add_bytes(b, g, width); |
374 | 1.44M | s->llviddsp.add_bytes(r, g, width); |
375 | 1.44M | b += p->linesize[0]; |
376 | 1.44M | g += p->linesize[1]; |
377 | 1.44M | r += p->linesize[2]; |
378 | 1.44M | } |
379 | 4.03k | } |
380 | | |
381 | 11.8k | return 0; |
382 | 15.9k | } |
383 | | |
384 | | static int build_huffman(AVCodecContext *avctx, const uint8_t *table, |
385 | | int table_size, int max) |
386 | 23.4k | { |
387 | 23.4k | MagicYUVContext *s = avctx->priv_data; |
388 | 23.4k | GetByteContext gb; |
389 | 23.4k | uint8_t *len = s->len; |
390 | 23.4k | uint16_t length_count[33] = { 0 }; |
391 | 23.4k | int i = 0, j = 0, k; |
392 | | |
393 | 23.4k | bytestream2_init(&gb, table, table_size); |
394 | | |
395 | 210k | while (bytestream2_get_bytes_left(&gb) > 0) { |
396 | 210k | int b = bytestream2_peek_byteu(&gb) & 0x80; |
397 | 210k | int x = bytestream2_get_byteu(&gb) & ~0x80; |
398 | 210k | int l = 1; |
399 | | |
400 | 210k | if (b) { |
401 | 188k | if (bytestream2_get_bytes_left(&gb) <= 0) |
402 | 229 | break; |
403 | 187k | l += bytestream2_get_byteu(&gb); |
404 | 187k | } |
405 | 210k | k = j + l; |
406 | 210k | if (k > max || x == 0 || x > 32) { |
407 | 1.82k | av_log(avctx, AV_LOG_ERROR, "Invalid Huffman codes\n"); |
408 | 1.82k | return AVERROR_INVALIDDATA; |
409 | 1.82k | } |
410 | | |
411 | 208k | length_count[x] += l; |
412 | 31.6M | for (; j < k; j++) |
413 | 31.4M | len[j] = x; |
414 | | |
415 | 208k | if (j == max) { |
416 | 46.7k | j = 0; |
417 | 46.7k | if (huff_build(avctx, len, length_count, &s->vlc[i], &s->multi[i], max, avctx)) { |
418 | 663 | av_log(avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n"); |
419 | 663 | return AVERROR_INVALIDDATA; |
420 | 663 | } |
421 | 46.0k | i++; |
422 | 46.0k | if (i == s->planes) { |
423 | 20.4k | break; |
424 | 20.4k | } |
425 | 25.5k | memset(length_count, 0, sizeof(length_count)); |
426 | 25.5k | } |
427 | 208k | } |
428 | | |
429 | 20.9k | if (i != s->planes) { |
430 | 505 | av_log(avctx, AV_LOG_ERROR, "Huffman tables too short\n"); |
431 | 505 | return AVERROR_INVALIDDATA; |
432 | 505 | } |
433 | | |
434 | 20.4k | return 0; |
435 | 20.9k | } |
436 | | |
437 | | static int magy_decode_frame(AVCodecContext *avctx, AVFrame *p, |
438 | | int *got_frame, AVPacket *avpkt) |
439 | 67.9k | { |
440 | 67.9k | MagicYUVContext *s = avctx->priv_data; |
441 | 67.9k | GetByteContext gb; |
442 | 67.9k | uint32_t first_offset, offset, next_offset, header_size, slice_width; |
443 | 67.9k | int width, height, format, version, table_size; |
444 | 67.9k | int ret, i, j; |
445 | | |
446 | 67.9k | if (avpkt->size < 36) |
447 | 22.5k | return AVERROR_INVALIDDATA; |
448 | | |
449 | 45.3k | bytestream2_init(&gb, avpkt->data, avpkt->size); |
450 | 45.3k | if (bytestream2_get_le32u(&gb) != MKTAG('M', 'A', 'G', 'Y')) |
451 | 5.62k | return AVERROR_INVALIDDATA; |
452 | | |
453 | 39.7k | header_size = bytestream2_get_le32u(&gb); |
454 | 39.7k | if (header_size < 32 || header_size >= avpkt->size) { |
455 | 3.10k | av_log(avctx, AV_LOG_ERROR, |
456 | 3.10k | "header or packet too small %"PRIu32"\n", header_size); |
457 | 3.10k | return AVERROR_INVALIDDATA; |
458 | 3.10k | } |
459 | | |
460 | 36.6k | version = bytestream2_get_byteu(&gb); |
461 | 36.6k | if (version != 7) { |
462 | 414 | avpriv_request_sample(avctx, "Version %d", version); |
463 | 414 | return AVERROR_PATCHWELCOME; |
464 | 414 | } |
465 | | |
466 | 36.2k | format = bytestream2_get_byteu(&gb); |
467 | 36.2k | switch (format) { |
468 | 6.33k | case 0x65: |
469 | 6.33k | avctx->pix_fmt = AV_PIX_FMT_GBRP; |
470 | 6.33k | break; |
471 | 1.98k | case 0x66: |
472 | 1.98k | avctx->pix_fmt = AV_PIX_FMT_GBRAP; |
473 | 1.98k | break; |
474 | 2.93k | case 0x67: |
475 | 2.93k | avctx->pix_fmt = AV_PIX_FMT_YUV444P; |
476 | 2.93k | break; |
477 | 423 | case 0x68: |
478 | 423 | avctx->pix_fmt = AV_PIX_FMT_YUV422P; |
479 | 423 | break; |
480 | 454 | case 0x69: |
481 | 454 | avctx->pix_fmt = AV_PIX_FMT_YUV420P; |
482 | 454 | break; |
483 | 355 | case 0x6a: |
484 | 355 | avctx->pix_fmt = AV_PIX_FMT_YUVA444P; |
485 | 355 | break; |
486 | 9.25k | case 0x6b: |
487 | 9.25k | avctx->pix_fmt = AV_PIX_FMT_GRAY8; |
488 | 9.25k | break; |
489 | 1.85k | case 0x6c: |
490 | 1.85k | avctx->pix_fmt = AV_PIX_FMT_YUV422P10; |
491 | 1.85k | break; |
492 | 817 | case 0x76: |
493 | 817 | avctx->pix_fmt = AV_PIX_FMT_YUV444P10; |
494 | 817 | break; |
495 | 2.17k | case 0x6d: |
496 | 2.17k | avctx->pix_fmt = AV_PIX_FMT_GBRP10; |
497 | 2.17k | break; |
498 | 78 | case 0x6e: |
499 | 78 | avctx->pix_fmt = AV_PIX_FMT_GBRAP10; |
500 | 78 | break; |
501 | 4 | case 0x6f: |
502 | 4 | avctx->pix_fmt = AV_PIX_FMT_GBRP12; |
503 | 4 | break; |
504 | 1.92k | case 0x70: |
505 | 1.92k | avctx->pix_fmt = AV_PIX_FMT_GBRAP12; |
506 | 1.92k | break; |
507 | 346 | case 0x71: |
508 | 346 | avctx->pix_fmt = AV_PIX_FMT_GBRP14; |
509 | 346 | break; |
510 | 57 | case 0x72: |
511 | 57 | avctx->pix_fmt = AV_PIX_FMT_GBRAP14; |
512 | 57 | break; |
513 | 6.09k | case 0x73: |
514 | 6.09k | avctx->pix_fmt = AV_PIX_FMT_GRAY10; |
515 | 6.09k | break; |
516 | 425 | case 0x7b: |
517 | 425 | avctx->pix_fmt = AV_PIX_FMT_YUV420P10; |
518 | 425 | break; |
519 | 723 | default: |
520 | 723 | avpriv_request_sample(avctx, "Format 0x%X", format); |
521 | 723 | return AVERROR_PATCHWELCOME; |
522 | 36.2k | } |
523 | 35.5k | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); |
524 | 35.5k | av_assert1(desc); |
525 | 35.5k | int is_rgb = s->decorrelate = !!(desc->flags & AV_PIX_FMT_FLAG_RGB); |
526 | 35.5k | s->hshift[1] = s->hshift[2] = desc->log2_chroma_w; |
527 | 35.5k | s->vshift[1] = s->vshift[2] = desc->log2_chroma_h; |
528 | 35.5k | s->bps = desc->comp[0].depth; |
529 | 35.5k | s->max = 1 << s->bps; |
530 | 35.5k | s->magy_decode_slice = s->bps == 8 ? magy_decode_slice : magy_decode_slice10; |
531 | 35.5k | s->planes = av_pix_fmt_count_planes(avctx->pix_fmt); |
532 | | |
533 | 35.5k | bytestream2_skipu(&gb, 1); |
534 | 35.5k | s->color_matrix = bytestream2_get_byteu(&gb); |
535 | 35.5k | s->flags = bytestream2_get_byteu(&gb); |
536 | 35.5k | s->interlaced = !!(s->flags & 2); |
537 | 35.5k | bytestream2_skipu(&gb, 3); |
538 | | |
539 | 35.5k | width = bytestream2_get_le32u(&gb); |
540 | 35.5k | height = bytestream2_get_le32u(&gb); |
541 | 35.5k | ret = ff_set_dimensions(avctx, width, height); |
542 | 35.5k | if (ret < 0) |
543 | 4.75k | return ret; |
544 | | |
545 | 30.7k | slice_width = bytestream2_get_le32u(&gb); |
546 | 30.7k | if (slice_width != avctx->coded_width) { |
547 | 1.34k | avpriv_request_sample(avctx, "Slice width %"PRIu32, slice_width); |
548 | 1.34k | return AVERROR_PATCHWELCOME; |
549 | 1.34k | } |
550 | 29.4k | s->slice_height = bytestream2_get_le32u(&gb); |
551 | 29.4k | if (s->slice_height <= 0 || s->slice_height > INT_MAX - avctx->coded_height) { |
552 | 511 | av_log(avctx, AV_LOG_ERROR, |
553 | 511 | "invalid slice height: %d\n", s->slice_height); |
554 | 511 | return AVERROR_INVALIDDATA; |
555 | 511 | } |
556 | | |
557 | 28.9k | bytestream2_skipu(&gb, 4); |
558 | | |
559 | 28.9k | s->nb_slices = (avctx->coded_height + s->slice_height - 1) / s->slice_height; |
560 | 28.9k | if (s->nb_slices > INT_MAX / FFMAX(sizeof(Slice), 4 * 5)) { |
561 | 0 | av_log(avctx, AV_LOG_ERROR, |
562 | 0 | "invalid number of slices: %d\n", s->nb_slices); |
563 | 0 | return AVERROR_INVALIDDATA; |
564 | 0 | } |
565 | | |
566 | 28.9k | if (s->interlaced) { |
567 | 9.22k | if ((s->slice_height >> s->vshift[1]) < 2) { |
568 | 338 | av_log(avctx, AV_LOG_ERROR, "impossible slice height\n"); |
569 | 338 | return AVERROR_INVALIDDATA; |
570 | 338 | } |
571 | 8.88k | if ((avctx->coded_height % s->slice_height) && ((avctx->coded_height % s->slice_height) >> s->vshift[1]) < 2) { |
572 | 203 | av_log(avctx, AV_LOG_ERROR, "impossible height\n"); |
573 | 203 | return AVERROR_INVALIDDATA; |
574 | 203 | } |
575 | 8.88k | } |
576 | | |
577 | 28.3k | if (bytestream2_get_bytes_left(&gb) <= s->nb_slices * s->planes * 5) |
578 | 322 | return AVERROR_INVALIDDATA; |
579 | 83.7k | for (i = 0; i < s->planes; i++) { |
580 | 58.6k | av_fast_malloc(&s->slices[i], &s->slices_size[i], s->nb_slices * sizeof(Slice)); |
581 | 58.6k | if (!s->slices[i]) |
582 | 0 | return AVERROR(ENOMEM); |
583 | | |
584 | 58.6k | offset = bytestream2_get_le32u(&gb); |
585 | 58.6k | if (offset >= avpkt->size - header_size) |
586 | 1.74k | return AVERROR_INVALIDDATA; |
587 | | |
588 | 56.8k | if (i == 0) |
589 | 26.8k | first_offset = offset; |
590 | | |
591 | 57.6k | for (j = 0; j < s->nb_slices - 1; j++) { |
592 | 1.73k | s->slices[i][j].start = offset + header_size; |
593 | | |
594 | 1.73k | next_offset = bytestream2_get_le32u(&gb); |
595 | 1.73k | if (next_offset <= offset || next_offset >= avpkt->size - header_size) |
596 | 435 | return AVERROR_INVALIDDATA; |
597 | | |
598 | 1.29k | s->slices[i][j].size = next_offset - offset; |
599 | 1.29k | if (s->slices[i][j].size < 2) |
600 | 578 | return AVERROR_INVALIDDATA; |
601 | 720 | offset = next_offset; |
602 | 720 | } |
603 | | |
604 | 55.8k | s->slices[i][j].start = offset + header_size; |
605 | 55.8k | s->slices[i][j].size = avpkt->size - s->slices[i][j].start; |
606 | | |
607 | 55.8k | if (s->slices[i][j].size < 2) |
608 | 212 | return AVERROR_INVALIDDATA; |
609 | 55.8k | } |
610 | | |
611 | 25.0k | if (bytestream2_get_byteu(&gb) != s->planes) |
612 | 648 | return AVERROR_INVALIDDATA; |
613 | | |
614 | 24.4k | bytestream2_skipu(&gb, s->nb_slices * s->planes); |
615 | | |
616 | 24.4k | table_size = header_size + first_offset - bytestream2_tell(&gb); |
617 | 24.4k | if (table_size < 2) |
618 | 966 | return AVERROR_INVALIDDATA; |
619 | | |
620 | 23.4k | ret = build_huffman(avctx, avpkt->data + bytestream2_tell(&gb), |
621 | 23.4k | table_size, s->max); |
622 | 23.4k | if (ret < 0) |
623 | 2.99k | return ret; |
624 | | |
625 | 20.4k | if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) |
626 | 20 | return ret; |
627 | | |
628 | 20.4k | s->buf = avpkt->data; |
629 | 20.4k | s->p = p; |
630 | 20.4k | avctx->execute2(avctx, s->magy_decode_slice, NULL, NULL, s->nb_slices); |
631 | | |
632 | 20.4k | if (is_rgb) { |
633 | 6.58k | FFSWAP(uint8_t*, p->data[0], p->data[1]); |
634 | 6.58k | FFSWAP(int, p->linesize[0], p->linesize[1]); |
635 | 13.8k | } else { |
636 | 13.8k | switch (s->color_matrix) { |
637 | 4.09k | case 1: |
638 | 4.09k | p->colorspace = AVCOL_SPC_BT470BG; |
639 | 4.09k | break; |
640 | 564 | case 2: |
641 | 564 | p->colorspace = AVCOL_SPC_BT709; |
642 | 564 | break; |
643 | 13.8k | } |
644 | 13.8k | p->color_range = (s->flags & 4) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; |
645 | 13.8k | } |
646 | | |
647 | 20.4k | *got_frame = 1; |
648 | | |
649 | 20.4k | return avpkt->size; |
650 | 20.4k | } |
651 | | |
652 | | static av_cold int magy_decode_init(AVCodecContext *avctx) |
653 | 2.82k | { |
654 | 2.82k | MagicYUVContext *s = avctx->priv_data; |
655 | 2.82k | ff_llviddsp_init(&s->llviddsp); |
656 | 2.82k | return 0; |
657 | 2.82k | } |
658 | | |
659 | | static av_cold int magy_decode_end(AVCodecContext *avctx) |
660 | 2.82k | { |
661 | 2.82k | MagicYUVContext * const s = avctx->priv_data; |
662 | 2.82k | int i; |
663 | | |
664 | 14.1k | for (i = 0; i < FF_ARRAY_ELEMS(s->slices); i++) { |
665 | 11.2k | av_freep(&s->slices[i]); |
666 | 11.2k | s->slices_size[i] = 0; |
667 | 11.2k | ff_vlc_free(&s->vlc[i]); |
668 | 11.2k | ff_vlc_free_multi(&s->multi[i]); |
669 | 11.2k | } |
670 | | |
671 | 2.82k | return 0; |
672 | 2.82k | } |
673 | | |
674 | | const FFCodec ff_magicyuv_decoder = { |
675 | | .p.name = "magicyuv", |
676 | | CODEC_LONG_NAME("MagicYUV video"), |
677 | | .p.type = AVMEDIA_TYPE_VIDEO, |
678 | | .p.id = AV_CODEC_ID_MAGICYUV, |
679 | | .priv_data_size = sizeof(MagicYUVContext), |
680 | | .init = magy_decode_init, |
681 | | .close = magy_decode_end, |
682 | | FF_CODEC_DECODE_CB(magy_decode_frame), |
683 | | .p.capabilities = AV_CODEC_CAP_DR1 | |
684 | | AV_CODEC_CAP_FRAME_THREADS | |
685 | | AV_CODEC_CAP_SLICE_THREADS, |
686 | | }; |