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