1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * LCL (LossLess Codec Library) Codec
3cabdff1aSopenharmony_ci * Copyright (c) 2002-2004 Roberto Togni
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/**
23cabdff1aSopenharmony_ci * @file
24cabdff1aSopenharmony_ci * LCL (LossLess Codec Library) Video Codec
25cabdff1aSopenharmony_ci * Decoder for MSZH and ZLIB codecs
26cabdff1aSopenharmony_ci * Experimental encoder for ZLIB RGB24
27cabdff1aSopenharmony_ci *
28cabdff1aSopenharmony_ci * Fourcc: MSZH, ZLIB
29cabdff1aSopenharmony_ci *
30cabdff1aSopenharmony_ci * Original Win32 dll:
31cabdff1aSopenharmony_ci * Ver2.23 By Kenji Oshima 2000.09.20
32cabdff1aSopenharmony_ci * avimszh.dll, avizlib.dll
33cabdff1aSopenharmony_ci *
34cabdff1aSopenharmony_ci * A description of the decoding algorithm can be found here:
35cabdff1aSopenharmony_ci *   http://www.pcisys.net/~melanson/codecs
36cabdff1aSopenharmony_ci *
37cabdff1aSopenharmony_ci * Supports: BGR24 (RGB 24bpp)
38cabdff1aSopenharmony_ci */
39cabdff1aSopenharmony_ci
40cabdff1aSopenharmony_ci#include "config_components.h"
41cabdff1aSopenharmony_ci
42cabdff1aSopenharmony_ci#include <stdio.h>
43cabdff1aSopenharmony_ci#include <stdlib.h>
44cabdff1aSopenharmony_ci
45cabdff1aSopenharmony_ci#include "libavutil/mem.h"
46cabdff1aSopenharmony_ci#include "libavutil/pixdesc.h"
47cabdff1aSopenharmony_ci#include "avcodec.h"
48cabdff1aSopenharmony_ci#include "bytestream.h"
49cabdff1aSopenharmony_ci#include "codec_internal.h"
50cabdff1aSopenharmony_ci#include "lcl.h"
51cabdff1aSopenharmony_ci#include "thread.h"
52cabdff1aSopenharmony_ci
53cabdff1aSopenharmony_ci#if CONFIG_ZLIB_DECODER
54cabdff1aSopenharmony_ci#include "zlib_wrapper.h"
55cabdff1aSopenharmony_ci#include <zlib.h>
56cabdff1aSopenharmony_ci#endif
57cabdff1aSopenharmony_ci
58cabdff1aSopenharmony_citypedef struct LclDecContext {
59cabdff1aSopenharmony_ci    // Image type
60cabdff1aSopenharmony_ci    int imgtype;
61cabdff1aSopenharmony_ci    // Compression type
62cabdff1aSopenharmony_ci    int compression;
63cabdff1aSopenharmony_ci    // Flags
64cabdff1aSopenharmony_ci    int flags;
65cabdff1aSopenharmony_ci    // Decompressed data size
66cabdff1aSopenharmony_ci    unsigned int decomp_size;
67cabdff1aSopenharmony_ci    // Decompression buffer
68cabdff1aSopenharmony_ci    unsigned char* decomp_buf;
69cabdff1aSopenharmony_ci#if CONFIG_ZLIB_DECODER
70cabdff1aSopenharmony_ci    FFZStream zstream;
71cabdff1aSopenharmony_ci#endif
72cabdff1aSopenharmony_ci} LclDecContext;
73cabdff1aSopenharmony_ci
74cabdff1aSopenharmony_ci
75cabdff1aSopenharmony_ci/**
76cabdff1aSopenharmony_ci * @param srcptr compressed source buffer, must be padded with at least 5 extra bytes
77cabdff1aSopenharmony_ci * @param destptr must be padded sufficiently for av_memcpy_backptr
78cabdff1aSopenharmony_ci */
79cabdff1aSopenharmony_cistatic unsigned int mszh_decomp(const unsigned char * srcptr, int srclen, unsigned char * destptr, unsigned int destsize)
80cabdff1aSopenharmony_ci{
81cabdff1aSopenharmony_ci    unsigned char *destptr_bak = destptr;
82cabdff1aSopenharmony_ci    unsigned char *destptr_end = destptr + destsize;
83cabdff1aSopenharmony_ci    const unsigned char *srcptr_end = srcptr + srclen;
84cabdff1aSopenharmony_ci    unsigned mask = *srcptr++;
85cabdff1aSopenharmony_ci    unsigned maskbit = 0x80;
86cabdff1aSopenharmony_ci
87cabdff1aSopenharmony_ci    while (srcptr < srcptr_end && destptr < destptr_end) {
88cabdff1aSopenharmony_ci        if (!(mask & maskbit)) {
89cabdff1aSopenharmony_ci            memcpy(destptr, srcptr, 4);
90cabdff1aSopenharmony_ci            destptr += 4;
91cabdff1aSopenharmony_ci            srcptr += 4;
92cabdff1aSopenharmony_ci        } else {
93cabdff1aSopenharmony_ci            unsigned ofs = bytestream_get_le16(&srcptr);
94cabdff1aSopenharmony_ci            unsigned cnt = (ofs >> 11) + 1;
95cabdff1aSopenharmony_ci            ofs &= 0x7ff;
96cabdff1aSopenharmony_ci            ofs = FFMIN(ofs, destptr - destptr_bak);
97cabdff1aSopenharmony_ci            cnt *= 4;
98cabdff1aSopenharmony_ci            cnt = FFMIN(cnt, destptr_end - destptr);
99cabdff1aSopenharmony_ci            if (ofs) {
100cabdff1aSopenharmony_ci                av_memcpy_backptr(destptr, ofs, cnt);
101cabdff1aSopenharmony_ci            } else {
102cabdff1aSopenharmony_ci                // Not known what the correct behaviour is, but
103cabdff1aSopenharmony_ci                // this at least avoids uninitialized data.
104cabdff1aSopenharmony_ci                memset(destptr, 0, cnt);
105cabdff1aSopenharmony_ci            }
106cabdff1aSopenharmony_ci            destptr += cnt;
107cabdff1aSopenharmony_ci        }
108cabdff1aSopenharmony_ci        maskbit >>= 1;
109cabdff1aSopenharmony_ci        if (!maskbit) {
110cabdff1aSopenharmony_ci            mask = *srcptr++;
111cabdff1aSopenharmony_ci            while (!mask) {
112cabdff1aSopenharmony_ci                if (destptr_end - destptr < 32 || srcptr_end - srcptr < 32) break;
113cabdff1aSopenharmony_ci                memcpy(destptr, srcptr, 32);
114cabdff1aSopenharmony_ci                destptr += 32;
115cabdff1aSopenharmony_ci                srcptr += 32;
116cabdff1aSopenharmony_ci                mask = *srcptr++;
117cabdff1aSopenharmony_ci            }
118cabdff1aSopenharmony_ci            maskbit = 0x80;
119cabdff1aSopenharmony_ci        }
120cabdff1aSopenharmony_ci    }
121cabdff1aSopenharmony_ci
122cabdff1aSopenharmony_ci    return destptr - destptr_bak;
123cabdff1aSopenharmony_ci}
124cabdff1aSopenharmony_ci
125cabdff1aSopenharmony_ci
126cabdff1aSopenharmony_ci#if CONFIG_ZLIB_DECODER
127cabdff1aSopenharmony_ci/**
128cabdff1aSopenharmony_ci * @brief decompress a zlib-compressed data block into decomp_buf
129cabdff1aSopenharmony_ci * @param src compressed input buffer
130cabdff1aSopenharmony_ci * @param src_len data length in input buffer
131cabdff1aSopenharmony_ci * @param offset offset in decomp_buf
132cabdff1aSopenharmony_ci * @param expected expected decompressed length
133cabdff1aSopenharmony_ci */
134cabdff1aSopenharmony_cistatic int zlib_decomp(AVCodecContext *avctx, const uint8_t *src, int src_len, int offset, int expected)
135cabdff1aSopenharmony_ci{
136cabdff1aSopenharmony_ci    LclDecContext *c = avctx->priv_data;
137cabdff1aSopenharmony_ci    z_stream *const zstream = &c->zstream.zstream;
138cabdff1aSopenharmony_ci    int zret = inflateReset(zstream);
139cabdff1aSopenharmony_ci    if (zret != Z_OK) {
140cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret);
141cabdff1aSopenharmony_ci        return AVERROR_UNKNOWN;
142cabdff1aSopenharmony_ci    }
143cabdff1aSopenharmony_ci    zstream->next_in   = src;
144cabdff1aSopenharmony_ci    zstream->avail_in  = src_len;
145cabdff1aSopenharmony_ci    zstream->next_out  = c->decomp_buf + offset;
146cabdff1aSopenharmony_ci    zstream->avail_out = c->decomp_size - offset;
147cabdff1aSopenharmony_ci    zret = inflate(zstream, Z_FINISH);
148cabdff1aSopenharmony_ci    if (zret != Z_OK && zret != Z_STREAM_END) {
149cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Inflate error: %d\n", zret);
150cabdff1aSopenharmony_ci        return AVERROR_UNKNOWN;
151cabdff1aSopenharmony_ci    }
152cabdff1aSopenharmony_ci    if (expected != (unsigned int)zstream->total_out) {
153cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Decoded size differs (%d != %lu)\n",
154cabdff1aSopenharmony_ci               expected, zstream->total_out);
155cabdff1aSopenharmony_ci        if (expected > (unsigned int)zstream->total_out)
156cabdff1aSopenharmony_ci            return (unsigned int)zstream->total_out;
157cabdff1aSopenharmony_ci        return AVERROR_UNKNOWN;
158cabdff1aSopenharmony_ci    }
159cabdff1aSopenharmony_ci    return zstream->total_out;
160cabdff1aSopenharmony_ci}
161cabdff1aSopenharmony_ci#endif
162cabdff1aSopenharmony_ci
163cabdff1aSopenharmony_ci
164cabdff1aSopenharmony_cistatic int decode_frame(AVCodecContext *avctx, AVFrame *frame,
165cabdff1aSopenharmony_ci                        int *got_frame, AVPacket *avpkt)
166cabdff1aSopenharmony_ci{
167cabdff1aSopenharmony_ci    const uint8_t *buf = avpkt->data;
168cabdff1aSopenharmony_ci    int buf_size = avpkt->size;
169cabdff1aSopenharmony_ci    LclDecContext * const c = avctx->priv_data;
170cabdff1aSopenharmony_ci    unsigned int pixel_ptr;
171cabdff1aSopenharmony_ci    int row, col;
172cabdff1aSopenharmony_ci    unsigned char *encoded = avpkt->data, *outptr;
173cabdff1aSopenharmony_ci    uint8_t *y_out, *u_out, *v_out;
174cabdff1aSopenharmony_ci    int width = avctx->width; // Real image width
175cabdff1aSopenharmony_ci    int height = avctx->height; // Real image height
176cabdff1aSopenharmony_ci    unsigned int mszh_dlen;
177cabdff1aSopenharmony_ci    unsigned char yq, y1q, uq, vq;
178cabdff1aSopenharmony_ci    int uqvq, ret;
179cabdff1aSopenharmony_ci    unsigned int mthread_inlen, mthread_outlen;
180cabdff1aSopenharmony_ci    unsigned int len = buf_size;
181cabdff1aSopenharmony_ci    int linesize, offset;
182cabdff1aSopenharmony_ci
183cabdff1aSopenharmony_ci    if ((ret = ff_thread_get_buffer(avctx, frame, 0)) < 0)
184cabdff1aSopenharmony_ci        return ret;
185cabdff1aSopenharmony_ci
186cabdff1aSopenharmony_ci    outptr = frame->data[0]; // Output image pointer
187cabdff1aSopenharmony_ci
188cabdff1aSopenharmony_ci    /* Decompress frame */
189cabdff1aSopenharmony_ci    switch (avctx->codec_id) {
190cabdff1aSopenharmony_ci    case AV_CODEC_ID_MSZH:
191cabdff1aSopenharmony_ci        switch (c->compression) {
192cabdff1aSopenharmony_ci        case COMP_MSZH:
193cabdff1aSopenharmony_ci            if (c->imgtype == IMGTYPE_RGB24 && len == FFALIGN(width * 3, 4) * height ||
194cabdff1aSopenharmony_ci                c->imgtype == IMGTYPE_YUV111 && len == width * height * 3) {
195cabdff1aSopenharmony_ci                ;
196cabdff1aSopenharmony_ci            } else if (c->flags & FLAG_MULTITHREAD) {
197cabdff1aSopenharmony_ci                mthread_inlen = AV_RL32(buf);
198cabdff1aSopenharmony_ci                if (len < 8 || len - 8 < mthread_inlen) {
199cabdff1aSopenharmony_ci                    av_log(avctx, AV_LOG_ERROR, "len %d is too small\n", len);
200cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
201cabdff1aSopenharmony_ci                }
202cabdff1aSopenharmony_ci                mthread_outlen = AV_RL32(buf + 4);
203cabdff1aSopenharmony_ci                mthread_outlen = FFMIN(mthread_outlen, c->decomp_size);
204cabdff1aSopenharmony_ci                mszh_dlen = mszh_decomp(buf + 8, mthread_inlen, c->decomp_buf, c->decomp_size);
205cabdff1aSopenharmony_ci                if (mthread_outlen != mszh_dlen) {
206cabdff1aSopenharmony_ci                    av_log(avctx, AV_LOG_ERROR, "Mthread1 decoded size differs (%d != %d)\n",
207cabdff1aSopenharmony_ci                           mthread_outlen, mszh_dlen);
208cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
209cabdff1aSopenharmony_ci                }
210cabdff1aSopenharmony_ci                mszh_dlen = mszh_decomp(buf + 8 + mthread_inlen, len - 8 - mthread_inlen,
211cabdff1aSopenharmony_ci                                        c->decomp_buf + mthread_outlen, c->decomp_size - mthread_outlen);
212cabdff1aSopenharmony_ci                if (mthread_outlen != mszh_dlen) {
213cabdff1aSopenharmony_ci                    av_log(avctx, AV_LOG_ERROR, "Mthread2 decoded size differs (%d != %d)\n",
214cabdff1aSopenharmony_ci                           mthread_outlen, mszh_dlen);
215cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
216cabdff1aSopenharmony_ci                }
217cabdff1aSopenharmony_ci                encoded = c->decomp_buf;
218cabdff1aSopenharmony_ci                len = c->decomp_size;
219cabdff1aSopenharmony_ci            } else {
220cabdff1aSopenharmony_ci                mszh_dlen = mszh_decomp(buf, len, c->decomp_buf, c->decomp_size);
221cabdff1aSopenharmony_ci                if (c->decomp_size != mszh_dlen) {
222cabdff1aSopenharmony_ci                    av_log(avctx, AV_LOG_ERROR, "Decoded size differs (%d != %d)\n",
223cabdff1aSopenharmony_ci                           c->decomp_size, mszh_dlen);
224cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
225cabdff1aSopenharmony_ci                }
226cabdff1aSopenharmony_ci                encoded = c->decomp_buf;
227cabdff1aSopenharmony_ci                len = mszh_dlen;
228cabdff1aSopenharmony_ci            }
229cabdff1aSopenharmony_ci            break;
230cabdff1aSopenharmony_ci        case COMP_MSZH_NOCOMP: {
231cabdff1aSopenharmony_ci            int bppx2;
232cabdff1aSopenharmony_ci            int aligned_width = width;
233cabdff1aSopenharmony_ci            switch (c->imgtype) {
234cabdff1aSopenharmony_ci            case IMGTYPE_YUV111:
235cabdff1aSopenharmony_ci            case IMGTYPE_RGB24:
236cabdff1aSopenharmony_ci                bppx2 = 6;
237cabdff1aSopenharmony_ci                break;
238cabdff1aSopenharmony_ci            case IMGTYPE_YUV422:
239cabdff1aSopenharmony_ci                aligned_width &= ~3;
240cabdff1aSopenharmony_ci            case IMGTYPE_YUV211:
241cabdff1aSopenharmony_ci                bppx2 = 4;
242cabdff1aSopenharmony_ci                break;
243cabdff1aSopenharmony_ci            case IMGTYPE_YUV411:
244cabdff1aSopenharmony_ci                aligned_width &= ~3;
245cabdff1aSopenharmony_ci            case IMGTYPE_YUV420:
246cabdff1aSopenharmony_ci                bppx2 = 3;
247cabdff1aSopenharmony_ci                break;
248cabdff1aSopenharmony_ci            default:
249cabdff1aSopenharmony_ci                bppx2 = 0; // will error out below
250cabdff1aSopenharmony_ci                break;
251cabdff1aSopenharmony_ci            }
252cabdff1aSopenharmony_ci            if (len < ((aligned_width * height * bppx2) >> 1))
253cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
254cabdff1aSopenharmony_ci            break;
255cabdff1aSopenharmony_ci        }
256cabdff1aSopenharmony_ci        default:
257cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR, "BUG! Unknown MSZH compression in frame decoder.\n");
258cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
259cabdff1aSopenharmony_ci        }
260cabdff1aSopenharmony_ci        break;
261cabdff1aSopenharmony_ci#if CONFIG_ZLIB_DECODER
262cabdff1aSopenharmony_ci    case AV_CODEC_ID_ZLIB:
263cabdff1aSopenharmony_ci        /* Using the original dll with normal compression (-1) and RGB format
264cabdff1aSopenharmony_ci         * gives a file with ZLIB fourcc, but frame is really uncompressed.
265cabdff1aSopenharmony_ci         * To be sure that's true check also frame size */
266cabdff1aSopenharmony_ci        if (c->compression == COMP_ZLIB_NORMAL && c->imgtype == IMGTYPE_RGB24 &&
267cabdff1aSopenharmony_ci            len == width * height * 3) {
268cabdff1aSopenharmony_ci            if (c->flags & FLAG_PNGFILTER) {
269cabdff1aSopenharmony_ci                memcpy(c->decomp_buf, buf, len);
270cabdff1aSopenharmony_ci                encoded = c->decomp_buf;
271cabdff1aSopenharmony_ci            } else {
272cabdff1aSopenharmony_ci                break;
273cabdff1aSopenharmony_ci            }
274cabdff1aSopenharmony_ci        } else if (c->flags & FLAG_MULTITHREAD) {
275cabdff1aSopenharmony_ci            mthread_inlen = AV_RL32(buf);
276cabdff1aSopenharmony_ci            mthread_inlen = FFMIN(mthread_inlen, len - 8);
277cabdff1aSopenharmony_ci            mthread_outlen = AV_RL32(buf + 4);
278cabdff1aSopenharmony_ci            mthread_outlen = FFMIN(mthread_outlen, c->decomp_size);
279cabdff1aSopenharmony_ci            ret = zlib_decomp(avctx, buf + 8, mthread_inlen, 0, mthread_outlen);
280cabdff1aSopenharmony_ci            if (ret < 0) return ret;
281cabdff1aSopenharmony_ci            ret = zlib_decomp(avctx, buf + 8 + mthread_inlen, len - 8 - mthread_inlen,
282cabdff1aSopenharmony_ci                              mthread_outlen, mthread_outlen);
283cabdff1aSopenharmony_ci            if (ret < 0) return ret;
284cabdff1aSopenharmony_ci            len = c->decomp_size;
285cabdff1aSopenharmony_ci        } else {
286cabdff1aSopenharmony_ci            int ret = zlib_decomp(avctx, buf, len, 0, c->decomp_size);
287cabdff1aSopenharmony_ci            if (ret < 0) return ret;
288cabdff1aSopenharmony_ci            len = ret;
289cabdff1aSopenharmony_ci        }
290cabdff1aSopenharmony_ci        encoded = c->decomp_buf;
291cabdff1aSopenharmony_ci        break;
292cabdff1aSopenharmony_ci#endif
293cabdff1aSopenharmony_ci    default:
294cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "BUG! Unknown codec in frame decoder compression switch.\n");
295cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
296cabdff1aSopenharmony_ci    }
297cabdff1aSopenharmony_ci
298cabdff1aSopenharmony_ci
299cabdff1aSopenharmony_ci    /* Apply PNG filter */
300cabdff1aSopenharmony_ci    if (avctx->codec_id == AV_CODEC_ID_ZLIB && (c->flags & FLAG_PNGFILTER)) {
301cabdff1aSopenharmony_ci        switch (c->imgtype) {
302cabdff1aSopenharmony_ci        case IMGTYPE_YUV111:
303cabdff1aSopenharmony_ci        case IMGTYPE_RGB24:
304cabdff1aSopenharmony_ci            for (row = 0; row < height; row++) {
305cabdff1aSopenharmony_ci                pixel_ptr = row * width * 3;
306cabdff1aSopenharmony_ci                yq = encoded[pixel_ptr++];
307cabdff1aSopenharmony_ci                uqvq = AV_RL16(encoded+pixel_ptr);
308cabdff1aSopenharmony_ci                pixel_ptr += 2;
309cabdff1aSopenharmony_ci                for (col = 1; col < width; col++) {
310cabdff1aSopenharmony_ci                    encoded[pixel_ptr] = yq -= encoded[pixel_ptr];
311cabdff1aSopenharmony_ci                    uqvq -= AV_RL16(encoded+pixel_ptr+1);
312cabdff1aSopenharmony_ci                    AV_WL16(encoded+pixel_ptr+1, uqvq);
313cabdff1aSopenharmony_ci                    pixel_ptr += 3;
314cabdff1aSopenharmony_ci                }
315cabdff1aSopenharmony_ci            }
316cabdff1aSopenharmony_ci            break;
317cabdff1aSopenharmony_ci        case IMGTYPE_YUV422:
318cabdff1aSopenharmony_ci            pixel_ptr = 0;
319cabdff1aSopenharmony_ci            for (row = 0; row < height; row++) {
320cabdff1aSopenharmony_ci                yq = uq = vq =0;
321cabdff1aSopenharmony_ci                for (col = 0; col < width/4; col++) {
322cabdff1aSopenharmony_ci                    encoded[pixel_ptr] = yq -= encoded[pixel_ptr];
323cabdff1aSopenharmony_ci                    encoded[pixel_ptr+1] = yq -= encoded[pixel_ptr+1];
324cabdff1aSopenharmony_ci                    encoded[pixel_ptr+2] = yq -= encoded[pixel_ptr+2];
325cabdff1aSopenharmony_ci                    encoded[pixel_ptr+3] = yq -= encoded[pixel_ptr+3];
326cabdff1aSopenharmony_ci                    encoded[pixel_ptr+4] = uq -= encoded[pixel_ptr+4];
327cabdff1aSopenharmony_ci                    encoded[pixel_ptr+5] = uq -= encoded[pixel_ptr+5];
328cabdff1aSopenharmony_ci                    encoded[pixel_ptr+6] = vq -= encoded[pixel_ptr+6];
329cabdff1aSopenharmony_ci                    encoded[pixel_ptr+7] = vq -= encoded[pixel_ptr+7];
330cabdff1aSopenharmony_ci                    pixel_ptr += 8;
331cabdff1aSopenharmony_ci                }
332cabdff1aSopenharmony_ci            }
333cabdff1aSopenharmony_ci            break;
334cabdff1aSopenharmony_ci        case IMGTYPE_YUV411:
335cabdff1aSopenharmony_ci            pixel_ptr = 0;
336cabdff1aSopenharmony_ci            for (row = 0; row < height; row++) {
337cabdff1aSopenharmony_ci                yq = uq = vq =0;
338cabdff1aSopenharmony_ci                for (col = 0; col < width/4; col++) {
339cabdff1aSopenharmony_ci                    encoded[pixel_ptr] = yq -= encoded[pixel_ptr];
340cabdff1aSopenharmony_ci                    encoded[pixel_ptr+1] = yq -= encoded[pixel_ptr+1];
341cabdff1aSopenharmony_ci                    encoded[pixel_ptr+2] = yq -= encoded[pixel_ptr+2];
342cabdff1aSopenharmony_ci                    encoded[pixel_ptr+3] = yq -= encoded[pixel_ptr+3];
343cabdff1aSopenharmony_ci                    encoded[pixel_ptr+4] = uq -= encoded[pixel_ptr+4];
344cabdff1aSopenharmony_ci                    encoded[pixel_ptr+5] = vq -= encoded[pixel_ptr+5];
345cabdff1aSopenharmony_ci                    pixel_ptr += 6;
346cabdff1aSopenharmony_ci                }
347cabdff1aSopenharmony_ci            }
348cabdff1aSopenharmony_ci            break;
349cabdff1aSopenharmony_ci        case IMGTYPE_YUV211:
350cabdff1aSopenharmony_ci            for (row = 0; row < height; row++) {
351cabdff1aSopenharmony_ci                pixel_ptr = row * width * 2;
352cabdff1aSopenharmony_ci                yq = uq = vq =0;
353cabdff1aSopenharmony_ci                for (col = 0; col < width/2; col++) {
354cabdff1aSopenharmony_ci                    encoded[pixel_ptr] = yq -= encoded[pixel_ptr];
355cabdff1aSopenharmony_ci                    encoded[pixel_ptr+1] = yq -= encoded[pixel_ptr+1];
356cabdff1aSopenharmony_ci                    encoded[pixel_ptr+2] = uq -= encoded[pixel_ptr+2];
357cabdff1aSopenharmony_ci                    encoded[pixel_ptr+3] = vq -= encoded[pixel_ptr+3];
358cabdff1aSopenharmony_ci                    pixel_ptr += 4;
359cabdff1aSopenharmony_ci                }
360cabdff1aSopenharmony_ci            }
361cabdff1aSopenharmony_ci            break;
362cabdff1aSopenharmony_ci        case IMGTYPE_YUV420:
363cabdff1aSopenharmony_ci            for (row = 0; row < height/2; row++) {
364cabdff1aSopenharmony_ci                pixel_ptr = row * width * 3;
365cabdff1aSopenharmony_ci                yq = y1q = uq = vq =0;
366cabdff1aSopenharmony_ci                for (col = 0; col < width/2; col++) {
367cabdff1aSopenharmony_ci                    encoded[pixel_ptr] = yq -= encoded[pixel_ptr];
368cabdff1aSopenharmony_ci                    encoded[pixel_ptr+1] = yq -= encoded[pixel_ptr+1];
369cabdff1aSopenharmony_ci                    encoded[pixel_ptr+2] = y1q -= encoded[pixel_ptr+2];
370cabdff1aSopenharmony_ci                    encoded[pixel_ptr+3] = y1q -= encoded[pixel_ptr+3];
371cabdff1aSopenharmony_ci                    encoded[pixel_ptr+4] = uq -= encoded[pixel_ptr+4];
372cabdff1aSopenharmony_ci                    encoded[pixel_ptr+5] = vq -= encoded[pixel_ptr+5];
373cabdff1aSopenharmony_ci                    pixel_ptr += 6;
374cabdff1aSopenharmony_ci                }
375cabdff1aSopenharmony_ci            }
376cabdff1aSopenharmony_ci            break;
377cabdff1aSopenharmony_ci        default:
378cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR, "BUG! Unknown imagetype in pngfilter switch.\n");
379cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
380cabdff1aSopenharmony_ci        }
381cabdff1aSopenharmony_ci    }
382cabdff1aSopenharmony_ci
383cabdff1aSopenharmony_ci    /* Convert colorspace */
384cabdff1aSopenharmony_ci    y_out = frame->data[0] + (height - 1) * frame->linesize[0];
385cabdff1aSopenharmony_ci    offset = (height - 1) * frame->linesize[1];
386cabdff1aSopenharmony_ci    u_out = FF_PTR_ADD(frame->data[1], offset);
387cabdff1aSopenharmony_ci    offset = (height - 1) * frame->linesize[2];
388cabdff1aSopenharmony_ci    v_out = FF_PTR_ADD(frame->data[2], offset);
389cabdff1aSopenharmony_ci    switch (c->imgtype) {
390cabdff1aSopenharmony_ci    case IMGTYPE_YUV111:
391cabdff1aSopenharmony_ci        for (row = 0; row < height; row++) {
392cabdff1aSopenharmony_ci            for (col = 0; col < width; col++) {
393cabdff1aSopenharmony_ci                y_out[col] = *encoded++;
394cabdff1aSopenharmony_ci                u_out[col] = *encoded++ + 128;
395cabdff1aSopenharmony_ci                v_out[col] = *encoded++ + 128;
396cabdff1aSopenharmony_ci            }
397cabdff1aSopenharmony_ci            y_out -= frame->linesize[0];
398cabdff1aSopenharmony_ci            u_out -= frame->linesize[1];
399cabdff1aSopenharmony_ci            v_out -= frame->linesize[2];
400cabdff1aSopenharmony_ci        }
401cabdff1aSopenharmony_ci        break;
402cabdff1aSopenharmony_ci    case IMGTYPE_YUV422:
403cabdff1aSopenharmony_ci        for (row = 0; row < height; row++) {
404cabdff1aSopenharmony_ci            for (col = 0; col < width - 3; col += 4) {
405cabdff1aSopenharmony_ci                memcpy(y_out + col, encoded, 4);
406cabdff1aSopenharmony_ci                encoded += 4;
407cabdff1aSopenharmony_ci                u_out[ col >> 1     ] = *encoded++ + 128;
408cabdff1aSopenharmony_ci                u_out[(col >> 1) + 1] = *encoded++ + 128;
409cabdff1aSopenharmony_ci                v_out[ col >> 1     ] = *encoded++ + 128;
410cabdff1aSopenharmony_ci                v_out[(col >> 1) + 1] = *encoded++ + 128;
411cabdff1aSopenharmony_ci            }
412cabdff1aSopenharmony_ci            if (col && col < width) {
413cabdff1aSopenharmony_ci                u_out[ col >> 1     ] = u_out[(col>>1) - 1];
414cabdff1aSopenharmony_ci                v_out[ col >> 1     ] = v_out[(col>>1) - 1];
415cabdff1aSopenharmony_ci            }
416cabdff1aSopenharmony_ci
417cabdff1aSopenharmony_ci            y_out -= frame->linesize[0];
418cabdff1aSopenharmony_ci            u_out -= frame->linesize[1];
419cabdff1aSopenharmony_ci            v_out -= frame->linesize[2];
420cabdff1aSopenharmony_ci        }
421cabdff1aSopenharmony_ci        break;
422cabdff1aSopenharmony_ci    case IMGTYPE_RGB24:
423cabdff1aSopenharmony_ci        linesize = len < FFALIGN(3 * width, 4) * height ? 3 * width : FFALIGN(3 * width, 4);
424cabdff1aSopenharmony_ci        for (row = height - 1; row >= 0; row--) {
425cabdff1aSopenharmony_ci            pixel_ptr = row * frame->linesize[0];
426cabdff1aSopenharmony_ci            memcpy(outptr + pixel_ptr, encoded, 3 * width);
427cabdff1aSopenharmony_ci            encoded += linesize;
428cabdff1aSopenharmony_ci        }
429cabdff1aSopenharmony_ci        break;
430cabdff1aSopenharmony_ci    case IMGTYPE_YUV411:
431cabdff1aSopenharmony_ci        for (row = 0; row < height; row++) {
432cabdff1aSopenharmony_ci            for (col = 0; col < width - 3; col += 4) {
433cabdff1aSopenharmony_ci                memcpy(y_out + col, encoded, 4);
434cabdff1aSopenharmony_ci                encoded += 4;
435cabdff1aSopenharmony_ci                u_out[col >> 2] = *encoded++ + 128;
436cabdff1aSopenharmony_ci                v_out[col >> 2] = *encoded++ + 128;
437cabdff1aSopenharmony_ci            }
438cabdff1aSopenharmony_ci            if (col && col < width) {
439cabdff1aSopenharmony_ci                u_out[col >> 2] = u_out[(col>>2) - 1];
440cabdff1aSopenharmony_ci                v_out[col >> 2] = v_out[(col>>2) - 1];
441cabdff1aSopenharmony_ci            }
442cabdff1aSopenharmony_ci            y_out -= frame->linesize[0];
443cabdff1aSopenharmony_ci            u_out -= frame->linesize[1];
444cabdff1aSopenharmony_ci            v_out -= frame->linesize[2];
445cabdff1aSopenharmony_ci        }
446cabdff1aSopenharmony_ci        break;
447cabdff1aSopenharmony_ci    case IMGTYPE_YUV211:
448cabdff1aSopenharmony_ci        for (row = 0; row < height; row++) {
449cabdff1aSopenharmony_ci            for (col = 0; col < width - 1; col += 2) {
450cabdff1aSopenharmony_ci                memcpy(y_out + col, encoded, 2);
451cabdff1aSopenharmony_ci                encoded += 2;
452cabdff1aSopenharmony_ci                u_out[col >> 1] = *encoded++ + 128;
453cabdff1aSopenharmony_ci                v_out[col >> 1] = *encoded++ + 128;
454cabdff1aSopenharmony_ci            }
455cabdff1aSopenharmony_ci            y_out -= frame->linesize[0];
456cabdff1aSopenharmony_ci            u_out -= frame->linesize[1];
457cabdff1aSopenharmony_ci            v_out -= frame->linesize[2];
458cabdff1aSopenharmony_ci        }
459cabdff1aSopenharmony_ci        break;
460cabdff1aSopenharmony_ci    case IMGTYPE_YUV420:
461cabdff1aSopenharmony_ci        u_out = frame->data[1] + ((height >> 1) - 1) * frame->linesize[1];
462cabdff1aSopenharmony_ci        v_out = frame->data[2] + ((height >> 1) - 1) * frame->linesize[2];
463cabdff1aSopenharmony_ci        for (row = 0; row < height - 1; row += 2) {
464cabdff1aSopenharmony_ci            for (col = 0; col < width - 1; col += 2) {
465cabdff1aSopenharmony_ci                memcpy(y_out + col, encoded, 2);
466cabdff1aSopenharmony_ci                encoded += 2;
467cabdff1aSopenharmony_ci                memcpy(y_out + col - frame->linesize[0], encoded, 2);
468cabdff1aSopenharmony_ci                encoded += 2;
469cabdff1aSopenharmony_ci                u_out[col >> 1] = *encoded++ + 128;
470cabdff1aSopenharmony_ci                v_out[col >> 1] = *encoded++ + 128;
471cabdff1aSopenharmony_ci            }
472cabdff1aSopenharmony_ci            y_out -= frame->linesize[0] << 1;
473cabdff1aSopenharmony_ci            u_out -= frame->linesize[1];
474cabdff1aSopenharmony_ci            v_out -= frame->linesize[2];
475cabdff1aSopenharmony_ci        }
476cabdff1aSopenharmony_ci        break;
477cabdff1aSopenharmony_ci    default:
478cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "BUG! Unknown imagetype in image decoder.\n");
479cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
480cabdff1aSopenharmony_ci    }
481cabdff1aSopenharmony_ci
482cabdff1aSopenharmony_ci    frame->key_frame = 1;
483cabdff1aSopenharmony_ci    frame->pict_type = AV_PICTURE_TYPE_I;
484cabdff1aSopenharmony_ci
485cabdff1aSopenharmony_ci    *got_frame = 1;
486cabdff1aSopenharmony_ci
487cabdff1aSopenharmony_ci    /* always report that the buffer was completely consumed */
488cabdff1aSopenharmony_ci    return buf_size;
489cabdff1aSopenharmony_ci}
490cabdff1aSopenharmony_ci
491cabdff1aSopenharmony_cistatic av_cold int decode_init(AVCodecContext *avctx)
492cabdff1aSopenharmony_ci{
493cabdff1aSopenharmony_ci    LclDecContext * const c = avctx->priv_data;
494cabdff1aSopenharmony_ci    unsigned int basesize = avctx->width * avctx->height;
495cabdff1aSopenharmony_ci    unsigned int max_basesize = FFALIGN(avctx->width,  4) *
496cabdff1aSopenharmony_ci                                FFALIGN(avctx->height, 4);
497cabdff1aSopenharmony_ci    unsigned int max_decomp_size;
498cabdff1aSopenharmony_ci    int subsample_h, subsample_v;
499cabdff1aSopenharmony_ci    int partial_h_supported = 0;
500cabdff1aSopenharmony_ci
501cabdff1aSopenharmony_ci    if (avctx->extradata_size < 8) {
502cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Extradata size too small.\n");
503cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
504cabdff1aSopenharmony_ci    }
505cabdff1aSopenharmony_ci
506cabdff1aSopenharmony_ci    /* Check codec type */
507cabdff1aSopenharmony_ci    if ((avctx->codec_id == AV_CODEC_ID_MSZH  && avctx->extradata[7] != CODEC_MSZH) ||
508cabdff1aSopenharmony_ci        (avctx->codec_id == AV_CODEC_ID_ZLIB  && avctx->extradata[7] != CODEC_ZLIB)) {
509cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Codec id and codec type mismatch. This should not happen.\n");
510cabdff1aSopenharmony_ci    }
511cabdff1aSopenharmony_ci
512cabdff1aSopenharmony_ci    /* Detect image type */
513cabdff1aSopenharmony_ci    switch (c->imgtype = avctx->extradata[4]) {
514cabdff1aSopenharmony_ci    case IMGTYPE_YUV111:
515cabdff1aSopenharmony_ci        c->decomp_size = basesize * 3;
516cabdff1aSopenharmony_ci        max_decomp_size = max_basesize * 3;
517cabdff1aSopenharmony_ci        avctx->pix_fmt = AV_PIX_FMT_YUV444P;
518cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_DEBUG, "Image type is YUV 1:1:1.\n");
519cabdff1aSopenharmony_ci        break;
520cabdff1aSopenharmony_ci    case IMGTYPE_YUV422:
521cabdff1aSopenharmony_ci        c->decomp_size = (avctx->width & ~3) * avctx->height * 2;
522cabdff1aSopenharmony_ci        max_decomp_size = max_basesize * 2;
523cabdff1aSopenharmony_ci        avctx->pix_fmt = AV_PIX_FMT_YUV422P;
524cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_DEBUG, "Image type is YUV 4:2:2.\n");
525cabdff1aSopenharmony_ci        partial_h_supported = 1;
526cabdff1aSopenharmony_ci        break;
527cabdff1aSopenharmony_ci    case IMGTYPE_RGB24:
528cabdff1aSopenharmony_ci        c->decomp_size = FFALIGN(avctx->width*3, 4) * avctx->height;
529cabdff1aSopenharmony_ci        max_decomp_size = max_basesize * 3;
530cabdff1aSopenharmony_ci        avctx->pix_fmt = AV_PIX_FMT_BGR24;
531cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_DEBUG, "Image type is RGB 24.\n");
532cabdff1aSopenharmony_ci        break;
533cabdff1aSopenharmony_ci    case IMGTYPE_YUV411:
534cabdff1aSopenharmony_ci        c->decomp_size = (avctx->width & ~3) * avctx->height / 2 * 3;
535cabdff1aSopenharmony_ci        max_decomp_size = max_basesize / 2 * 3;
536cabdff1aSopenharmony_ci        avctx->pix_fmt = AV_PIX_FMT_YUV411P;
537cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_DEBUG, "Image type is YUV 4:1:1.\n");
538cabdff1aSopenharmony_ci        partial_h_supported = 1;
539cabdff1aSopenharmony_ci        break;
540cabdff1aSopenharmony_ci    case IMGTYPE_YUV211:
541cabdff1aSopenharmony_ci        c->decomp_size = basesize * 2;
542cabdff1aSopenharmony_ci        max_decomp_size = max_basesize * 2;
543cabdff1aSopenharmony_ci        avctx->pix_fmt = AV_PIX_FMT_YUV422P;
544cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_DEBUG, "Image type is YUV 2:1:1.\n");
545cabdff1aSopenharmony_ci        break;
546cabdff1aSopenharmony_ci    case IMGTYPE_YUV420:
547cabdff1aSopenharmony_ci        c->decomp_size = basesize / 2 * 3;
548cabdff1aSopenharmony_ci        max_decomp_size = max_basesize / 2 * 3;
549cabdff1aSopenharmony_ci        avctx->pix_fmt = AV_PIX_FMT_YUV420P;
550cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_DEBUG, "Image type is YUV 4:2:0.\n");
551cabdff1aSopenharmony_ci        break;
552cabdff1aSopenharmony_ci    default:
553cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Unsupported image format %d.\n", c->imgtype);
554cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
555cabdff1aSopenharmony_ci    }
556cabdff1aSopenharmony_ci
557cabdff1aSopenharmony_ci    av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &subsample_h, &subsample_v);
558cabdff1aSopenharmony_ci    if ((avctx->width % (1<<subsample_h) && !partial_h_supported) || avctx->height % (1<<subsample_v)) {
559cabdff1aSopenharmony_ci        avpriv_request_sample(avctx, "Unsupported dimensions");
560cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
561cabdff1aSopenharmony_ci    }
562cabdff1aSopenharmony_ci
563cabdff1aSopenharmony_ci    /* Detect compression method */
564cabdff1aSopenharmony_ci    c->compression = (int8_t)avctx->extradata[5];
565cabdff1aSopenharmony_ci    switch (avctx->codec_id) {
566cabdff1aSopenharmony_ci    case AV_CODEC_ID_MSZH:
567cabdff1aSopenharmony_ci        switch (c->compression) {
568cabdff1aSopenharmony_ci        case COMP_MSZH:
569cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_DEBUG, "Compression enabled.\n");
570cabdff1aSopenharmony_ci            break;
571cabdff1aSopenharmony_ci        case COMP_MSZH_NOCOMP:
572cabdff1aSopenharmony_ci            c->decomp_size = 0;
573cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_DEBUG, "No compression.\n");
574cabdff1aSopenharmony_ci            break;
575cabdff1aSopenharmony_ci        default:
576cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR, "Unsupported compression format for MSZH (%d).\n", c->compression);
577cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
578cabdff1aSopenharmony_ci        }
579cabdff1aSopenharmony_ci        break;
580cabdff1aSopenharmony_ci#if CONFIG_ZLIB_DECODER
581cabdff1aSopenharmony_ci    case AV_CODEC_ID_ZLIB:
582cabdff1aSopenharmony_ci        switch (c->compression) {
583cabdff1aSopenharmony_ci        case COMP_ZLIB_HISPEED:
584cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_DEBUG, "High speed compression.\n");
585cabdff1aSopenharmony_ci            break;
586cabdff1aSopenharmony_ci        case COMP_ZLIB_HICOMP:
587cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_DEBUG, "High compression.\n");
588cabdff1aSopenharmony_ci            break;
589cabdff1aSopenharmony_ci        case COMP_ZLIB_NORMAL:
590cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_DEBUG, "Normal compression.\n");
591cabdff1aSopenharmony_ci            break;
592cabdff1aSopenharmony_ci        default:
593cabdff1aSopenharmony_ci            if (c->compression < Z_NO_COMPRESSION || c->compression > Z_BEST_COMPRESSION) {
594cabdff1aSopenharmony_ci                av_log(avctx, AV_LOG_ERROR, "Unsupported compression level for ZLIB: (%d).\n", c->compression);
595cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
596cabdff1aSopenharmony_ci            }
597cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_DEBUG, "Compression level for ZLIB: (%d).\n", c->compression);
598cabdff1aSopenharmony_ci        }
599cabdff1aSopenharmony_ci        break;
600cabdff1aSopenharmony_ci#endif
601cabdff1aSopenharmony_ci    default:
602cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "BUG! Unknown codec in compression switch.\n");
603cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
604cabdff1aSopenharmony_ci    }
605cabdff1aSopenharmony_ci
606cabdff1aSopenharmony_ci    /* Allocate decompression buffer */
607cabdff1aSopenharmony_ci    if (c->decomp_size) {
608cabdff1aSopenharmony_ci        if (!(c->decomp_buf = av_malloc(max_decomp_size))) {
609cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n");
610cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
611cabdff1aSopenharmony_ci        }
612cabdff1aSopenharmony_ci    }
613cabdff1aSopenharmony_ci
614cabdff1aSopenharmony_ci    /* Detect flags */
615cabdff1aSopenharmony_ci    c->flags = avctx->extradata[6];
616cabdff1aSopenharmony_ci    if (c->flags & FLAG_MULTITHREAD)
617cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_DEBUG, "Multithread encoder flag set.\n");
618cabdff1aSopenharmony_ci    if (c->flags & FLAG_NULLFRAME)
619cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_DEBUG, "Nullframe insertion flag set.\n");
620cabdff1aSopenharmony_ci    if (avctx->codec_id == AV_CODEC_ID_ZLIB && (c->flags & FLAG_PNGFILTER))
621cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_DEBUG, "PNG filter flag set.\n");
622cabdff1aSopenharmony_ci    if (c->flags & FLAGMASK_UNUSED)
623cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Unknown flag set (%d).\n", c->flags);
624cabdff1aSopenharmony_ci
625cabdff1aSopenharmony_ci    /* If needed init zlib */
626cabdff1aSopenharmony_ci#if CONFIG_ZLIB_DECODER
627cabdff1aSopenharmony_ci    if (avctx->codec_id == AV_CODEC_ID_ZLIB)
628cabdff1aSopenharmony_ci        return ff_inflate_init(&c->zstream, avctx);
629cabdff1aSopenharmony_ci#endif
630cabdff1aSopenharmony_ci
631cabdff1aSopenharmony_ci    return 0;
632cabdff1aSopenharmony_ci}
633cabdff1aSopenharmony_ci
634cabdff1aSopenharmony_cistatic av_cold int decode_end(AVCodecContext *avctx)
635cabdff1aSopenharmony_ci{
636cabdff1aSopenharmony_ci    LclDecContext * const c = avctx->priv_data;
637cabdff1aSopenharmony_ci
638cabdff1aSopenharmony_ci    av_freep(&c->decomp_buf);
639cabdff1aSopenharmony_ci#if CONFIG_ZLIB_DECODER
640cabdff1aSopenharmony_ci    ff_inflate_end(&c->zstream);
641cabdff1aSopenharmony_ci#endif
642cabdff1aSopenharmony_ci
643cabdff1aSopenharmony_ci    return 0;
644cabdff1aSopenharmony_ci}
645cabdff1aSopenharmony_ci
646cabdff1aSopenharmony_ci#if CONFIG_MSZH_DECODER
647cabdff1aSopenharmony_ciconst FFCodec ff_mszh_decoder = {
648cabdff1aSopenharmony_ci    .p.name         = "mszh",
649cabdff1aSopenharmony_ci    .p.long_name    = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) MSZH"),
650cabdff1aSopenharmony_ci    .p.type         = AVMEDIA_TYPE_VIDEO,
651cabdff1aSopenharmony_ci    .p.id           = AV_CODEC_ID_MSZH,
652cabdff1aSopenharmony_ci    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
653cabdff1aSopenharmony_ci    .priv_data_size = sizeof(LclDecContext),
654cabdff1aSopenharmony_ci    .init           = decode_init,
655cabdff1aSopenharmony_ci    .close          = decode_end,
656cabdff1aSopenharmony_ci    FF_CODEC_DECODE_CB(decode_frame),
657cabdff1aSopenharmony_ci    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
658cabdff1aSopenharmony_ci};
659cabdff1aSopenharmony_ci#endif
660cabdff1aSopenharmony_ci
661cabdff1aSopenharmony_ci#if CONFIG_ZLIB_DECODER
662cabdff1aSopenharmony_ciconst FFCodec ff_zlib_decoder = {
663cabdff1aSopenharmony_ci    .p.name         = "zlib",
664cabdff1aSopenharmony_ci    .p.long_name    = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) ZLIB"),
665cabdff1aSopenharmony_ci    .p.type         = AVMEDIA_TYPE_VIDEO,
666cabdff1aSopenharmony_ci    .p.id           = AV_CODEC_ID_ZLIB,
667cabdff1aSopenharmony_ci    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
668cabdff1aSopenharmony_ci    .priv_data_size = sizeof(LclDecContext),
669cabdff1aSopenharmony_ci    .init           = decode_init,
670cabdff1aSopenharmony_ci    .close          = decode_end,
671cabdff1aSopenharmony_ci    FF_CODEC_DECODE_CB(decode_frame),
672cabdff1aSopenharmony_ci    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
673cabdff1aSopenharmony_ci};
674cabdff1aSopenharmony_ci#endif
675