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