blob: c4f7597866c18c409204c830bbcb11ae315acf77
1 | /* |
2 | * Apple Pixlet 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 <stdint.h> |
23 | |
24 | #include "libavutil/imgutils.h" |
25 | #include "libavutil/intmath.h" |
26 | #include "libavutil/opt.h" |
27 | |
28 | #include "avcodec.h" |
29 | #include "bytestream.h" |
30 | #include "get_bits.h" |
31 | #include "unary.h" |
32 | #include "internal.h" |
33 | #include "thread.h" |
34 | |
35 | #define NB_LEVELS 4 |
36 | |
37 | #define H 0 |
38 | #define V 1 |
39 | |
40 | typedef struct SubBand { |
41 | unsigned width, height; |
42 | unsigned size; |
43 | unsigned x, y; |
44 | } SubBand; |
45 | |
46 | typedef struct PixletContext { |
47 | AVClass *class; |
48 | |
49 | GetByteContext gb; |
50 | GetBitContext gbit; |
51 | |
52 | int levels; |
53 | int depth; |
54 | int h, w; |
55 | |
56 | int16_t *filter[2]; |
57 | int16_t *prediction; |
58 | int64_t scaling[4][2][NB_LEVELS]; |
59 | SubBand band[4][NB_LEVELS * 3 + 1]; |
60 | } PixletContext; |
61 | |
62 | static int init_decoder(AVCodecContext *avctx) |
63 | { |
64 | PixletContext *ctx = avctx->priv_data; |
65 | int i, plane; |
66 | |
67 | ctx->filter[0] = av_malloc_array(ctx->h, sizeof(int16_t)); |
68 | ctx->filter[1] = av_malloc_array(FFMAX(ctx->h, ctx->w) + 16, sizeof(int16_t)); |
69 | ctx->prediction = av_malloc_array((ctx->w >> NB_LEVELS), sizeof(int16_t)); |
70 | if (!ctx->filter[0] || !ctx->filter[1] || !ctx->prediction) |
71 | return AVERROR(ENOMEM); |
72 | |
73 | for (plane = 0; plane < 3; plane++) { |
74 | unsigned shift = plane > 0; |
75 | unsigned w = ctx->w >> shift; |
76 | unsigned h = ctx->h >> shift; |
77 | |
78 | ctx->band[plane][0].width = w >> NB_LEVELS; |
79 | ctx->band[plane][0].height = h >> NB_LEVELS; |
80 | ctx->band[plane][0].size = (w >> NB_LEVELS) * (h >> NB_LEVELS); |
81 | |
82 | for (i = 0; i < NB_LEVELS * 3; i++) { |
83 | unsigned scale = ctx->levels - (i / 3); |
84 | |
85 | ctx->band[plane][i + 1].width = w >> scale; |
86 | ctx->band[plane][i + 1].height = h >> scale; |
87 | ctx->band[plane][i + 1].size = (w >> scale) * (h >> scale); |
88 | |
89 | ctx->band[plane][i + 1].x = (w >> scale) * (((i + 1) % 3) != 2); |
90 | ctx->band[plane][i + 1].y = (h >> scale) * (((i + 1) % 3) != 1); |
91 | } |
92 | } |
93 | |
94 | return 0; |
95 | } |
96 | |
97 | static void free_buffers(AVCodecContext *avctx) |
98 | { |
99 | PixletContext *ctx = avctx->priv_data; |
100 | |
101 | av_freep(&ctx->filter[0]); |
102 | av_freep(&ctx->filter[1]); |
103 | av_freep(&ctx->prediction); |
104 | } |
105 | |
106 | static av_cold int pixlet_close(AVCodecContext *avctx) |
107 | { |
108 | PixletContext *ctx = avctx->priv_data; |
109 | free_buffers(avctx); |
110 | ctx->w = 0; |
111 | ctx->h = 0; |
112 | return 0; |
113 | } |
114 | |
115 | static av_cold int pixlet_init(AVCodecContext *avctx) |
116 | { |
117 | avctx->pix_fmt = AV_PIX_FMT_YUV420P16; |
118 | avctx->color_range = AVCOL_RANGE_JPEG; |
119 | return 0; |
120 | } |
121 | |
122 | static int read_low_coeffs(AVCodecContext *avctx, int16_t *dst, int size, int width, ptrdiff_t stride) |
123 | { |
124 | PixletContext *ctx = avctx->priv_data; |
125 | GetBitContext *b = &ctx->gbit; |
126 | unsigned cnt1, nbits, k, j = 0, i = 0; |
127 | int64_t value, state = 3; |
128 | int rlen, escape, flag = 0; |
129 | |
130 | while (i < size) { |
131 | nbits = FFMIN(ff_clz((state >> 8) + 3) ^ 0x1F, 14); |
132 | |
133 | cnt1 = get_unary(b, 0, 8); |
134 | if (cnt1 < 8) { |
135 | value = show_bits(b, nbits); |
136 | if (value <= 1) { |
137 | skip_bits(b, nbits - 1); |
138 | escape = ((1 << nbits) - 1) * cnt1; |
139 | } else { |
140 | skip_bits(b, nbits); |
141 | escape = value + ((1 << nbits) - 1) * cnt1 - 1; |
142 | } |
143 | } else { |
144 | escape = get_bits(b, 16); |
145 | } |
146 | |
147 | value = -((escape + flag) & 1) | 1; |
148 | dst[j++] = value * ((escape + flag + 1) >> 1); |
149 | i++; |
150 | if (j == width) { |
151 | j = 0; |
152 | dst += stride; |
153 | } |
154 | state = 120 * (escape + flag) + state - (120 * state >> 8); |
155 | flag = 0; |
156 | |
157 | if (state * 4 > 0xFF || i >= size) |
158 | continue; |
159 | |
160 | nbits = ((state + 8) >> 5) + (state ? ff_clz(state) : 32) - 24; |
161 | escape = av_mod_uintp2(16383, nbits); |
162 | cnt1 = get_unary(b, 0, 8); |
163 | if (cnt1 > 7) { |
164 | rlen = get_bits(b, 16); |
165 | } else { |
166 | value = show_bits(b, nbits); |
167 | if (value > 1) { |
168 | skip_bits(b, nbits); |
169 | rlen = value + escape * cnt1 - 1; |
170 | } else { |
171 | skip_bits(b, nbits - 1); |
172 | rlen = escape * cnt1; |
173 | } |
174 | } |
175 | |
176 | if (rlen > size - i) |
177 | return AVERROR_INVALIDDATA; |
178 | i += rlen; |
179 | |
180 | for (k = 0; k < rlen; k++) { |
181 | dst[j++] = 0; |
182 | if (j == width) { |
183 | j = 0; |
184 | dst += stride; |
185 | } |
186 | } |
187 | |
188 | state = 0; |
189 | flag = rlen < 0xFFFF ? 1 : 0; |
190 | } |
191 | |
192 | align_get_bits(b); |
193 | return get_bits_count(b) >> 3; |
194 | } |
195 | |
196 | static int read_high_coeffs(AVCodecContext *avctx, uint8_t *src, int16_t *dst, int size, |
197 | int c, int a, int d, |
198 | int width, ptrdiff_t stride) |
199 | { |
200 | PixletContext *ctx = avctx->priv_data; |
201 | GetBitContext *b = &ctx->gbit; |
202 | unsigned cnt1, shbits, rlen, nbits, length, i = 0, j = 0, k; |
203 | int ret, escape, pfx, value, yflag, xflag, flag = 0; |
204 | int64_t state = 3, tmp; |
205 | |
206 | if ((ret = init_get_bits8(b, src, bytestream2_get_bytes_left(&ctx->gb))) < 0) |
207 | return ret; |
208 | |
209 | if ((a >= 0) + (a ^ (a >> 31)) - (a >> 31) != 1) { |
210 | nbits = 33 - ff_clz((a >= 0) + (a ^ (a >> 31)) - (a >> 31) - 1); |
211 | if (nbits > 16) |
212 | return AVERROR_INVALIDDATA; |
213 | } else { |
214 | nbits = 1; |
215 | } |
216 | |
217 | length = 25 - nbits; |
218 | |
219 | while (i < size) { |
220 | if (state >> 8 != -3) { |
221 | value = ff_clz((state >> 8) + 3) ^ 0x1F; |
222 | } else { |
223 | value = -1; |
224 | } |
225 | |
226 | cnt1 = get_unary(b, 0, length); |
227 | |
228 | if (cnt1 >= length) { |
229 | cnt1 = get_bits(b, nbits); |
230 | } else { |
231 | pfx = 14 + ((((uint64_t)(value - 14)) >> 32) & (value - 14)); |
232 | cnt1 *= (1 << pfx) - 1; |
233 | shbits = show_bits(b, pfx); |
234 | if (shbits <= 1) { |
235 | skip_bits(b, pfx - 1); |
236 | } else { |
237 | skip_bits(b, pfx); |
238 | cnt1 += shbits - 1; |
239 | } |
240 | } |
241 | |
242 | xflag = flag + cnt1; |
243 | yflag = xflag; |
244 | |
245 | if (flag + cnt1 == 0) { |
246 | value = 0; |
247 | } else { |
248 | xflag &= 1u; |
249 | tmp = (int64_t)c * ((yflag + 1) >> 1) + (c >> 1); |
250 | value = xflag + (tmp ^ -xflag); |
251 | } |
252 | |
253 | i++; |
254 | dst[j++] = value; |
255 | if (j == width) { |
256 | j = 0; |
257 | dst += stride; |
258 | } |
259 | state += (int64_t)d * yflag - (d * state >> 8); |
260 | |
261 | flag = 0; |
262 | |
263 | if (state * 4 > 0xFF || i >= size) |
264 | continue; |
265 | |
266 | pfx = ((state + 8) >> 5) + (state ? ff_clz(state): 32) - 24; |
267 | escape = av_mod_uintp2(16383, pfx); |
268 | cnt1 = get_unary(b, 0, 8); |
269 | if (cnt1 < 8) { |
270 | if (pfx < 1 || pfx > 25) |
271 | return AVERROR_INVALIDDATA; |
272 | value = show_bits(b, pfx); |
273 | if (value > 1) { |
274 | skip_bits(b, pfx); |
275 | rlen = value + escape * cnt1 - 1; |
276 | } else { |
277 | skip_bits(b, pfx - 1); |
278 | rlen = escape * cnt1; |
279 | } |
280 | } else { |
281 | if (get_bits1(b)) |
282 | value = get_bits(b, 16); |
283 | else |
284 | value = get_bits(b, 8); |
285 | |
286 | rlen = value + 8 * escape; |
287 | } |
288 | |
289 | if (rlen > 0xFFFF || i + rlen > size) |
290 | return AVERROR_INVALIDDATA; |
291 | i += rlen; |
292 | |
293 | for (k = 0; k < rlen; k++) { |
294 | dst[j++] = 0; |
295 | if (j == width) { |
296 | j = 0; |
297 | dst += stride; |
298 | } |
299 | } |
300 | |
301 | state = 0; |
302 | flag = rlen < 0xFFFF ? 1 : 0; |
303 | } |
304 | |
305 | align_get_bits(b); |
306 | return get_bits_count(b) >> 3; |
307 | } |
308 | |
309 | static int read_highpass(AVCodecContext *avctx, uint8_t *ptr, int plane, AVFrame *frame) |
310 | { |
311 | PixletContext *ctx = avctx->priv_data; |
312 | ptrdiff_t stride = frame->linesize[plane] / 2; |
313 | int i, ret; |
314 | |
315 | for (i = 0; i < ctx->levels * 3; i++) { |
316 | int32_t a = bytestream2_get_be32(&ctx->gb); |
317 | int32_t b = bytestream2_get_be32(&ctx->gb); |
318 | int32_t c = bytestream2_get_be32(&ctx->gb); |
319 | int32_t d = bytestream2_get_be32(&ctx->gb); |
320 | int16_t *dest = (int16_t *)frame->data[plane] + ctx->band[plane][i + 1].x + |
321 | stride * ctx->band[plane][i + 1].y; |
322 | unsigned size = ctx->band[plane][i + 1].size; |
323 | uint32_t magic; |
324 | |
325 | magic = bytestream2_get_be32(&ctx->gb); |
326 | if (magic != 0xDEADBEEF) { |
327 | av_log(avctx, AV_LOG_ERROR, "wrong magic number: 0x%08"PRIX32 |
328 | " for plane %d, band %d\n", magic, plane, i); |
329 | return AVERROR_INVALIDDATA; |
330 | } |
331 | |
332 | ret = read_high_coeffs(avctx, ptr + bytestream2_tell(&ctx->gb), dest, size, |
333 | c, (b >= FFABS(a)) ? b : a, d, |
334 | ctx->band[plane][i + 1].width, stride); |
335 | if (ret < 0) { |
336 | av_log(avctx, AV_LOG_ERROR, "error in highpass coefficients for plane %d, band %d\n", plane, i); |
337 | return ret; |
338 | } |
339 | bytestream2_skip(&ctx->gb, ret); |
340 | } |
341 | |
342 | return 0; |
343 | } |
344 | |
345 | static void lowpass_prediction(int16_t *dst, int16_t *pred, int width, int height, ptrdiff_t stride) |
346 | { |
347 | int16_t val; |
348 | int i, j; |
349 | |
350 | memset(pred, 0, width * sizeof(*pred)); |
351 | |
352 | for (i = 0; i < height; i++) { |
353 | val = pred[0] + dst[0]; |
354 | dst[0] = pred[0] = val; |
355 | for (j = 1; j < width; j++) { |
356 | val = pred[j] + dst[j]; |
357 | dst[j] = pred[j] = val; |
358 | dst[j] += dst[j-1]; |
359 | } |
360 | dst += stride; |
361 | } |
362 | } |
363 | |
364 | static void filterfn(int16_t *dest, int16_t *tmp, unsigned size, int64_t scale) |
365 | { |
366 | int16_t *low, *high, *ll, *lh, *hl, *hh; |
367 | int hsize, i, j; |
368 | int64_t value; |
369 | |
370 | hsize = size >> 1; |
371 | low = tmp + 4; |
372 | high = &low[hsize + 8]; |
373 | |
374 | memcpy(low, dest, size); |
375 | memcpy(high, dest + hsize, size); |
376 | |
377 | ll = &low[hsize]; |
378 | lh = &low[hsize]; |
379 | hl = &high[hsize]; |
380 | hh = hl; |
381 | for (i = 4, j = 2; i; i--, j++, ll--, hh++, lh++, hl--) { |
382 | low[i - 5] = low[j - 1]; |
383 | lh[0] = ll[-1]; |
384 | high[i - 5] = high[j - 2]; |
385 | hh[0] = hl[-2]; |
386 | } |
387 | |
388 | for (i = 0; i < hsize; i++) { |
389 | value = (int64_t) low [i + 1] * -INT64_C(325392907) + |
390 | (int64_t) low [i + 0] * INT64_C(3687786320) + |
391 | (int64_t) low [i - 1] * -INT64_C(325392907) + |
392 | (int64_t) high[i + 0] * INT64_C(1518500249) + |
393 | (int64_t) high[i - 1] * INT64_C(1518500249); |
394 | dest[i * 2] = av_clip_int16(((value >> 32) * scale) >> 32); |
395 | } |
396 | |
397 | for (i = 0; i < hsize; i++) { |
398 | value = (int64_t) low [i + 2] * -INT64_C(65078576) + |
399 | (int64_t) low [i + 1] * INT64_C(1583578880) + |
400 | (int64_t) low [i + 0] * INT64_C(1583578880) + |
401 | (int64_t) low [i - 1] * -INT64_C(65078576) + |
402 | (int64_t) high[i + 1] * INT64_C(303700064) + |
403 | (int64_t) high[i + 0] * -INT64_C(3644400640) + |
404 | (int64_t) high[i - 1] * INT64_C(303700064); |
405 | dest[i * 2 + 1] = av_clip_int16(((value >> 32) * scale) >> 32); |
406 | } |
407 | } |
408 | |
409 | static void reconstruction(AVCodecContext *avctx, |
410 | int16_t *dest, unsigned width, unsigned height, ptrdiff_t stride, int nb_levels, |
411 | int64_t *scaling_H, int64_t *scaling_V) |
412 | { |
413 | PixletContext *ctx = avctx->priv_data; |
414 | unsigned scaled_width, scaled_height; |
415 | int64_t scale_H, scale_V; |
416 | int16_t *ptr, *tmp; |
417 | int i, j, k; |
418 | |
419 | scaled_height = height >> nb_levels; |
420 | scaled_width = width >> nb_levels; |
421 | tmp = ctx->filter[0]; |
422 | |
423 | for (i = 0; i < nb_levels; i++) { |
424 | scaled_width <<= 1; |
425 | scaled_height <<= 1; |
426 | scale_H = scaling_H[i]; |
427 | scale_V = scaling_V[i]; |
428 | |
429 | ptr = dest; |
430 | for (j = 0; j < scaled_height; j++) { |
431 | filterfn(ptr, ctx->filter[1], scaled_width, scale_V); |
432 | ptr += stride; |
433 | } |
434 | |
435 | for (j = 0; j < scaled_width; j++) { |
436 | ptr = dest + j; |
437 | for (k = 0; k < scaled_height; k++) { |
438 | tmp[k] = *ptr; |
439 | ptr += stride; |
440 | } |
441 | |
442 | filterfn(tmp, ctx->filter[1], scaled_height, scale_H); |
443 | |
444 | ptr = dest + j; |
445 | for (k = 0; k < scaled_height; k++) { |
446 | *ptr = tmp[k]; |
447 | ptr += stride; |
448 | } |
449 | } |
450 | } |
451 | } |
452 | |
453 | static void postprocess_luma(AVFrame *frame, int w, int h, int depth) |
454 | { |
455 | uint16_t *dsty = (uint16_t *)frame->data[0]; |
456 | int16_t *srcy = (int16_t *)frame->data[0]; |
457 | ptrdiff_t stridey = frame->linesize[0] / 2; |
458 | int i, j; |
459 | |
460 | for (j = 0; j < h; j++) { |
461 | for (i = 0; i < w; i++) { |
462 | if (srcy[i] <= 0) |
463 | dsty[i] = 0; |
464 | else if (srcy[i] > ((1 << depth) - 1)) |
465 | dsty[i] = 65535; |
466 | else |
467 | dsty[i] = ((int64_t) srcy[i] * srcy[i] * 65535) / |
468 | ((1 << depth) - 1) / ((1 << depth) - 1); |
469 | } |
470 | dsty += stridey; |
471 | srcy += stridey; |
472 | } |
473 | } |
474 | |
475 | static void postprocess_chroma(AVFrame *frame, int w, int h, int depth) |
476 | { |
477 | uint16_t *dstu = (uint16_t *)frame->data[1]; |
478 | uint16_t *dstv = (uint16_t *)frame->data[2]; |
479 | int16_t *srcu = (int16_t *)frame->data[1]; |
480 | int16_t *srcv = (int16_t *)frame->data[2]; |
481 | ptrdiff_t strideu = frame->linesize[1] / 2; |
482 | ptrdiff_t stridev = frame->linesize[2] / 2; |
483 | const unsigned add = 1 << (depth - 1); |
484 | const unsigned shift = 16 - depth; |
485 | int i, j; |
486 | |
487 | for (j = 0; j < h; j++) { |
488 | for (i = 0; i < w; i++) { |
489 | dstu[i] = av_clip_uintp2_c(add + srcu[i], depth) << shift; |
490 | dstv[i] = av_clip_uintp2_c(add + srcv[i], depth) << shift; |
491 | } |
492 | dstu += strideu; |
493 | dstv += stridev; |
494 | srcu += strideu; |
495 | srcv += stridev; |
496 | } |
497 | } |
498 | |
499 | static int decode_plane(AVCodecContext *avctx, int plane, AVPacket *avpkt, AVFrame *frame) |
500 | { |
501 | PixletContext *ctx = avctx->priv_data; |
502 | ptrdiff_t stride = frame->linesize[plane] / 2; |
503 | unsigned shift = plane > 0; |
504 | int16_t *dst; |
505 | int i, ret; |
506 | |
507 | for (i = ctx->levels - 1; i >= 0; i--) { |
508 | int32_t h = sign_extend(bytestream2_get_be32(&ctx->gb), 32); |
509 | int32_t v = sign_extend(bytestream2_get_be32(&ctx->gb), 32); |
510 | |
511 | if (!h || !v) |
512 | return AVERROR_INVALIDDATA; |
513 | |
514 | ctx->scaling[plane][H][i] = (1000000ULL << 32) / h; |
515 | ctx->scaling[plane][V][i] = (1000000ULL << 32) / v; |
516 | } |
517 | |
518 | bytestream2_skip(&ctx->gb, 4); |
519 | |
520 | dst = (int16_t *)frame->data[plane]; |
521 | dst[0] = sign_extend(bytestream2_get_be16(&ctx->gb), 16); |
522 | |
523 | if ((ret = init_get_bits8(&ctx->gbit, avpkt->data + bytestream2_tell(&ctx->gb), |
524 | bytestream2_get_bytes_left(&ctx->gb))) < 0) |
525 | return ret; |
526 | |
527 | ret = read_low_coeffs(avctx, dst + 1, ctx->band[plane][0].width - 1, ctx->band[plane][0].width - 1, 0); |
528 | if (ret < 0) { |
529 | av_log(avctx, AV_LOG_ERROR, "error in lowpass coefficients for plane %d, top row\n", plane); |
530 | return ret; |
531 | } |
532 | |
533 | ret = read_low_coeffs(avctx, dst + stride, ctx->band[plane][0].height - 1, 1, stride); |
534 | if (ret < 0) { |
535 | av_log(avctx, AV_LOG_ERROR, "error in lowpass coefficients for plane %d, left column\n", plane); |
536 | return ret; |
537 | } |
538 | |
539 | ret = read_low_coeffs(avctx, dst + stride + 1, |
540 | (ctx->band[plane][0].width - 1) * (ctx->band[plane][0].height - 1), |
541 | ctx->band[plane][0].width - 1, stride); |
542 | if (ret < 0) { |
543 | av_log(avctx, AV_LOG_ERROR, "error in lowpass coefficients for plane %d, rest\n", plane); |
544 | return ret; |
545 | } |
546 | |
547 | bytestream2_skip(&ctx->gb, ret); |
548 | if (bytestream2_get_bytes_left(&ctx->gb) <= 0) { |
549 | av_log(avctx, AV_LOG_ERROR, "no bytes left\n"); |
550 | return AVERROR_INVALIDDATA; |
551 | } |
552 | |
553 | ret = read_highpass(avctx, avpkt->data, plane, frame); |
554 | if (ret < 0) |
555 | return ret; |
556 | |
557 | lowpass_prediction(dst, ctx->prediction, |
558 | ctx->band[plane][0].width, ctx->band[plane][0].height, stride); |
559 | |
560 | reconstruction(avctx, (int16_t *)frame->data[plane], ctx->w >> shift, ctx->h >> shift, |
561 | stride, NB_LEVELS, ctx->scaling[plane][H], ctx->scaling[plane][V]); |
562 | |
563 | return 0; |
564 | } |
565 | |
566 | static int pixlet_decode_frame(AVCodecContext *avctx, void *data, |
567 | int *got_frame, AVPacket *avpkt) |
568 | { |
569 | PixletContext *ctx = avctx->priv_data; |
570 | int i, w, h, width, height, ret, version; |
571 | AVFrame *p = data; |
572 | ThreadFrame frame = { .f = data }; |
573 | uint32_t pktsize; |
574 | |
575 | bytestream2_init(&ctx->gb, avpkt->data, avpkt->size); |
576 | |
577 | pktsize = bytestream2_get_be32(&ctx->gb); |
578 | if (pktsize <= 44 || pktsize - 4 > bytestream2_get_bytes_left(&ctx->gb)) { |
579 | av_log(avctx, AV_LOG_ERROR, "Invalid packet size %"PRIu32"\n", pktsize); |
580 | return AVERROR_INVALIDDATA; |
581 | } |
582 | |
583 | version = bytestream2_get_le32(&ctx->gb); |
584 | if (version != 1) |
585 | avpriv_request_sample(avctx, "Version %d", version); |
586 | |
587 | bytestream2_skip(&ctx->gb, 4); |
588 | if (bytestream2_get_be32(&ctx->gb) != 1) |
589 | return AVERROR_INVALIDDATA; |
590 | bytestream2_skip(&ctx->gb, 4); |
591 | |
592 | width = bytestream2_get_be32(&ctx->gb); |
593 | height = bytestream2_get_be32(&ctx->gb); |
594 | |
595 | w = FFALIGN(width, 1 << (NB_LEVELS + 1)); |
596 | h = FFALIGN(height, 1 << (NB_LEVELS + 1)); |
597 | |
598 | ctx->levels = bytestream2_get_be32(&ctx->gb); |
599 | if (ctx->levels != NB_LEVELS) |
600 | return AVERROR_INVALIDDATA; |
601 | ctx->depth = bytestream2_get_be32(&ctx->gb); |
602 | if (ctx->depth < 8 || ctx->depth > 15) { |
603 | avpriv_request_sample(avctx, "Depth %d", ctx->depth); |
604 | return AVERROR_INVALIDDATA; |
605 | } |
606 | |
607 | ret = ff_set_dimensions(avctx, w, h); |
608 | if (ret < 0) |
609 | return ret; |
610 | avctx->width = width; |
611 | avctx->height = height; |
612 | |
613 | if (ctx->w != w || ctx->h != h) { |
614 | free_buffers(avctx); |
615 | ctx->w = w; |
616 | ctx->h = h; |
617 | |
618 | ret = init_decoder(avctx); |
619 | if (ret < 0) { |
620 | free_buffers(avctx); |
621 | ctx->w = 0; |
622 | ctx->h = 0; |
623 | return ret; |
624 | } |
625 | } |
626 | |
627 | bytestream2_skip(&ctx->gb, 8); |
628 | |
629 | p->pict_type = AV_PICTURE_TYPE_I; |
630 | p->key_frame = 1; |
631 | p->color_range = AVCOL_RANGE_JPEG; |
632 | |
633 | ret = ff_thread_get_buffer(avctx, &frame, 0); |
634 | if (ret < 0) |
635 | return ret; |
636 | |
637 | for (i = 0; i < 3; i++) { |
638 | ret = decode_plane(avctx, i, avpkt, frame.f); |
639 | if (ret < 0) |
640 | return ret; |
641 | if (avctx->flags & AV_CODEC_FLAG_GRAY) |
642 | break; |
643 | } |
644 | |
645 | postprocess_luma(frame.f, ctx->w, ctx->h, ctx->depth); |
646 | postprocess_chroma(frame.f, ctx->w >> 1, ctx->h >> 1, ctx->depth); |
647 | |
648 | *got_frame = 1; |
649 | |
650 | return pktsize; |
651 | } |
652 | |
653 | #if HAVE_THREADS |
654 | static int pixlet_init_thread_copy(AVCodecContext *avctx) |
655 | { |
656 | PixletContext *ctx = avctx->priv_data; |
657 | |
658 | ctx->filter[0] = NULL; |
659 | ctx->filter[1] = NULL; |
660 | ctx->prediction = NULL; |
661 | ctx->w = ctx->h = 0; |
662 | |
663 | return 0; |
664 | } |
665 | #endif |
666 | |
667 | AVCodec ff_pixlet_decoder = { |
668 | .name = "pixlet", |
669 | .long_name = NULL_IF_CONFIG_SMALL("Apple Pixlet"), |
670 | .type = AVMEDIA_TYPE_VIDEO, |
671 | .id = AV_CODEC_ID_PIXLET, |
672 | .init = pixlet_init, |
673 | .init_thread_copy = ONLY_IF_THREADS_ENABLED(pixlet_init_thread_copy), |
674 | .close = pixlet_close, |
675 | .decode = pixlet_decode_frame, |
676 | .priv_data_size = sizeof(PixletContext), |
677 | .capabilities = AV_CODEC_CAP_DR1 | |
678 | AV_CODEC_CAP_FRAME_THREADS, |
679 | .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | |
680 | FF_CODEC_CAP_INIT_CLEANUP, |
681 | }; |
682 |