1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Mandsoft Screen Capture Codec decoder
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * Copyright (c) 2017 Paul B Mahol
5cabdff1aSopenharmony_ci *
6cabdff1aSopenharmony_ci * This file is part of FFmpeg.
7cabdff1aSopenharmony_ci *
8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
12cabdff1aSopenharmony_ci *
13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16cabdff1aSopenharmony_ci * Lesser General Public License for more details.
17cabdff1aSopenharmony_ci *
18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21cabdff1aSopenharmony_ci */
22cabdff1aSopenharmony_ci
23cabdff1aSopenharmony_ci#include <stdio.h>
24cabdff1aSopenharmony_ci#include <stdlib.h>
25cabdff1aSopenharmony_ci#include <string.h>
26cabdff1aSopenharmony_ci
27cabdff1aSopenharmony_ci#include "avcodec.h"
28cabdff1aSopenharmony_ci#include "bytestream.h"
29cabdff1aSopenharmony_ci#include "codec_internal.h"
30cabdff1aSopenharmony_ci#include "internal.h"
31cabdff1aSopenharmony_ci#include "zlib_wrapper.h"
32cabdff1aSopenharmony_ci
33cabdff1aSopenharmony_ci#include <zlib.h>
34cabdff1aSopenharmony_ci
35cabdff1aSopenharmony_citypedef struct MSCCContext {
36cabdff1aSopenharmony_ci    unsigned          bpp;
37cabdff1aSopenharmony_ci    unsigned int      decomp_size;
38cabdff1aSopenharmony_ci    uint8_t          *decomp_buf;
39cabdff1aSopenharmony_ci    unsigned int      uncomp_size;
40cabdff1aSopenharmony_ci    uint8_t          *uncomp_buf;
41cabdff1aSopenharmony_ci    FFZStream         zstream;
42cabdff1aSopenharmony_ci
43cabdff1aSopenharmony_ci    uint32_t          pal[256];
44cabdff1aSopenharmony_ci} MSCCContext;
45cabdff1aSopenharmony_ci
46cabdff1aSopenharmony_cistatic int rle_uncompress(AVCodecContext *avctx, GetByteContext *gb, PutByteContext *pb)
47cabdff1aSopenharmony_ci{
48cabdff1aSopenharmony_ci    MSCCContext *s = avctx->priv_data;
49cabdff1aSopenharmony_ci    unsigned x = 0, y = 0;
50cabdff1aSopenharmony_ci
51cabdff1aSopenharmony_ci    while (bytestream2_get_bytes_left(gb) > 0) {
52cabdff1aSopenharmony_ci        uint32_t fill;
53cabdff1aSopenharmony_ci        int j;
54cabdff1aSopenharmony_ci        unsigned run = bytestream2_get_byte(gb);
55cabdff1aSopenharmony_ci
56cabdff1aSopenharmony_ci        if (run) {
57cabdff1aSopenharmony_ci            switch (avctx->bits_per_coded_sample) {
58cabdff1aSopenharmony_ci            case 8:
59cabdff1aSopenharmony_ci                fill = bytestream2_get_byte(gb);
60cabdff1aSopenharmony_ci                break;
61cabdff1aSopenharmony_ci            case 16:
62cabdff1aSopenharmony_ci                fill = bytestream2_get_le16(gb);
63cabdff1aSopenharmony_ci                break;
64cabdff1aSopenharmony_ci            case 24:
65cabdff1aSopenharmony_ci                fill = bytestream2_get_le24(gb);
66cabdff1aSopenharmony_ci                break;
67cabdff1aSopenharmony_ci            case 32:
68cabdff1aSopenharmony_ci                fill = bytestream2_get_le32(gb);
69cabdff1aSopenharmony_ci                break;
70cabdff1aSopenharmony_ci            }
71cabdff1aSopenharmony_ci
72cabdff1aSopenharmony_ci            for (j = 0; j < run; j++) {
73cabdff1aSopenharmony_ci                switch (avctx->bits_per_coded_sample) {
74cabdff1aSopenharmony_ci                case 8:
75cabdff1aSopenharmony_ci                    bytestream2_put_byte(pb, fill);
76cabdff1aSopenharmony_ci                    break;
77cabdff1aSopenharmony_ci                case 16:
78cabdff1aSopenharmony_ci                    bytestream2_put_le16(pb, fill);
79cabdff1aSopenharmony_ci                    break;
80cabdff1aSopenharmony_ci                case 24:
81cabdff1aSopenharmony_ci                    bytestream2_put_le24(pb, fill);
82cabdff1aSopenharmony_ci                    break;
83cabdff1aSopenharmony_ci                case 32:
84cabdff1aSopenharmony_ci                    bytestream2_put_le32(pb, fill);
85cabdff1aSopenharmony_ci                    break;
86cabdff1aSopenharmony_ci                }
87cabdff1aSopenharmony_ci            }
88cabdff1aSopenharmony_ci            x += run;
89cabdff1aSopenharmony_ci        } else {
90cabdff1aSopenharmony_ci            unsigned copy = bytestream2_get_byte(gb);
91cabdff1aSopenharmony_ci
92cabdff1aSopenharmony_ci            if (copy == 0) {
93cabdff1aSopenharmony_ci                x = 0;
94cabdff1aSopenharmony_ci                y++;
95cabdff1aSopenharmony_ci                bytestream2_seek_p(pb, y * avctx->width * s->bpp, SEEK_SET);
96cabdff1aSopenharmony_ci            } else if (copy == 1) {
97cabdff1aSopenharmony_ci                return 0;
98cabdff1aSopenharmony_ci            } else if (copy == 2) {
99cabdff1aSopenharmony_ci
100cabdff1aSopenharmony_ci                x += bytestream2_get_byte(gb);
101cabdff1aSopenharmony_ci                y += bytestream2_get_byte(gb);
102cabdff1aSopenharmony_ci
103cabdff1aSopenharmony_ci                bytestream2_seek_p(pb, y * avctx->width * s->bpp + x * s->bpp, SEEK_SET);
104cabdff1aSopenharmony_ci            } else {
105cabdff1aSopenharmony_ci                for (j = 0; j < copy; j++) {
106cabdff1aSopenharmony_ci                    switch (avctx->bits_per_coded_sample) {
107cabdff1aSopenharmony_ci                    case 8:
108cabdff1aSopenharmony_ci                        bytestream2_put_byte(pb, bytestream2_get_byte(gb));
109cabdff1aSopenharmony_ci                        break;
110cabdff1aSopenharmony_ci                    case 16:
111cabdff1aSopenharmony_ci                        bytestream2_put_le16(pb, bytestream2_get_le16(gb));
112cabdff1aSopenharmony_ci                        break;
113cabdff1aSopenharmony_ci                    case 24:
114cabdff1aSopenharmony_ci                        bytestream2_put_le24(pb, bytestream2_get_le24(gb));
115cabdff1aSopenharmony_ci                        break;
116cabdff1aSopenharmony_ci                    case 32:
117cabdff1aSopenharmony_ci                        bytestream2_put_le32(pb, bytestream2_get_le32(gb));
118cabdff1aSopenharmony_ci                        break;
119cabdff1aSopenharmony_ci                    }
120cabdff1aSopenharmony_ci                }
121cabdff1aSopenharmony_ci
122cabdff1aSopenharmony_ci                if (s->bpp == 1 && (copy & 1))
123cabdff1aSopenharmony_ci                    bytestream2_skip(gb, 1);
124cabdff1aSopenharmony_ci                x += copy;
125cabdff1aSopenharmony_ci            }
126cabdff1aSopenharmony_ci        }
127cabdff1aSopenharmony_ci    }
128cabdff1aSopenharmony_ci
129cabdff1aSopenharmony_ci    return AVERROR_INVALIDDATA;
130cabdff1aSopenharmony_ci}
131cabdff1aSopenharmony_ci
132cabdff1aSopenharmony_cistatic int decode_frame(AVCodecContext *avctx, AVFrame *frame,
133cabdff1aSopenharmony_ci                        int *got_frame, AVPacket *avpkt)
134cabdff1aSopenharmony_ci{
135cabdff1aSopenharmony_ci    MSCCContext *s = avctx->priv_data;
136cabdff1aSopenharmony_ci    z_stream *const zstream = &s->zstream.zstream;
137cabdff1aSopenharmony_ci    const uint8_t *buf = avpkt->data;
138cabdff1aSopenharmony_ci    int buf_size = avpkt->size;
139cabdff1aSopenharmony_ci    GetByteContext gb;
140cabdff1aSopenharmony_ci    PutByteContext pb;
141cabdff1aSopenharmony_ci    int ret, j;
142cabdff1aSopenharmony_ci
143cabdff1aSopenharmony_ci    if (avpkt->size < 3)
144cabdff1aSopenharmony_ci        return buf_size;
145cabdff1aSopenharmony_ci
146cabdff1aSopenharmony_ci    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
147cabdff1aSopenharmony_ci        return ret;
148cabdff1aSopenharmony_ci
149cabdff1aSopenharmony_ci    if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
150cabdff1aSopenharmony_ci        size_t size;
151cabdff1aSopenharmony_ci        const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size);
152cabdff1aSopenharmony_ci
153cabdff1aSopenharmony_ci        if (pal && size == AVPALETTE_SIZE) {
154cabdff1aSopenharmony_ci            frame->palette_has_changed = 1;
155cabdff1aSopenharmony_ci            for (j = 0; j < 256; j++)
156cabdff1aSopenharmony_ci                s->pal[j] = 0xFF000000 | AV_RL32(pal + j * 4);
157cabdff1aSopenharmony_ci        } else if (pal) {
158cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR,
159cabdff1aSopenharmony_ci                   "Palette size %"SIZE_SPECIFIER" is wrong\n", size);
160cabdff1aSopenharmony_ci        }
161cabdff1aSopenharmony_ci        memcpy(frame->data[1], s->pal, AVPALETTE_SIZE);
162cabdff1aSopenharmony_ci    }
163cabdff1aSopenharmony_ci
164cabdff1aSopenharmony_ci    ret = inflateReset(zstream);
165cabdff1aSopenharmony_ci    if (ret != Z_OK) {
166cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret);
167cabdff1aSopenharmony_ci        return AVERROR_UNKNOWN;
168cabdff1aSopenharmony_ci    }
169cabdff1aSopenharmony_ci    zstream->next_out  = s->decomp_buf;
170cabdff1aSopenharmony_ci    zstream->avail_out = s->decomp_size;
171cabdff1aSopenharmony_ci    if (avctx->codec_id == AV_CODEC_ID_MSCC) {
172cabdff1aSopenharmony_ci        const uint8_t start = avpkt->data[2] ^ avpkt->data[0];
173cabdff1aSopenharmony_ci
174cabdff1aSopenharmony_ci        zstream->next_in  = &start;
175cabdff1aSopenharmony_ci        zstream->avail_in = 1;
176cabdff1aSopenharmony_ci        ret = inflate(zstream, Z_NO_FLUSH);
177cabdff1aSopenharmony_ci        if (ret != Z_OK || zstream->avail_in != 0)
178cabdff1aSopenharmony_ci            goto inflate_error;
179cabdff1aSopenharmony_ci
180cabdff1aSopenharmony_ci        buf      += 3;
181cabdff1aSopenharmony_ci        buf_size -= 3;
182cabdff1aSopenharmony_ci    }
183cabdff1aSopenharmony_ci    zstream->next_in   = buf;
184cabdff1aSopenharmony_ci    zstream->avail_in  = buf_size;
185cabdff1aSopenharmony_ci    ret = inflate(zstream, Z_FINISH);
186cabdff1aSopenharmony_ci    if (ret != Z_STREAM_END) {
187cabdff1aSopenharmony_ciinflate_error:
188cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Inflate error: %d\n", ret);
189cabdff1aSopenharmony_ci        return AVERROR_UNKNOWN;
190cabdff1aSopenharmony_ci    }
191cabdff1aSopenharmony_ci
192cabdff1aSopenharmony_ci    bytestream2_init(&gb, s->decomp_buf, zstream->total_out);
193cabdff1aSopenharmony_ci    bytestream2_init_writer(&pb, s->uncomp_buf, s->uncomp_size);
194cabdff1aSopenharmony_ci
195cabdff1aSopenharmony_ci    ret = rle_uncompress(avctx, &gb, &pb);
196cabdff1aSopenharmony_ci    if (ret)
197cabdff1aSopenharmony_ci        return ret;
198cabdff1aSopenharmony_ci
199cabdff1aSopenharmony_ci    for (j = 0; j < avctx->height; j++) {
200cabdff1aSopenharmony_ci        memcpy(frame->data[0] + (avctx->height - j - 1) * frame->linesize[0],
201cabdff1aSopenharmony_ci               s->uncomp_buf + s->bpp * j * avctx->width, s->bpp * avctx->width);
202cabdff1aSopenharmony_ci    }
203cabdff1aSopenharmony_ci
204cabdff1aSopenharmony_ci    frame->key_frame = 1;
205cabdff1aSopenharmony_ci    frame->pict_type = AV_PICTURE_TYPE_I;
206cabdff1aSopenharmony_ci
207cabdff1aSopenharmony_ci    *got_frame = 1;
208cabdff1aSopenharmony_ci
209cabdff1aSopenharmony_ci    return avpkt->size;
210cabdff1aSopenharmony_ci}
211cabdff1aSopenharmony_ci
212cabdff1aSopenharmony_cistatic av_cold int decode_init(AVCodecContext *avctx)
213cabdff1aSopenharmony_ci{
214cabdff1aSopenharmony_ci    MSCCContext *s = avctx->priv_data;
215cabdff1aSopenharmony_ci    int stride;
216cabdff1aSopenharmony_ci
217cabdff1aSopenharmony_ci    switch (avctx->bits_per_coded_sample) {
218cabdff1aSopenharmony_ci    case  8: avctx->pix_fmt = AV_PIX_FMT_PAL8;   break;
219cabdff1aSopenharmony_ci    case 16: avctx->pix_fmt = AV_PIX_FMT_RGB555; break;
220cabdff1aSopenharmony_ci    case 24: avctx->pix_fmt = AV_PIX_FMT_BGR24;  break;
221cabdff1aSopenharmony_ci    case 32: avctx->pix_fmt = AV_PIX_FMT_BGRA;   break;
222cabdff1aSopenharmony_ci    default:
223cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n", avctx->bits_per_coded_sample);
224cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
225cabdff1aSopenharmony_ci    }
226cabdff1aSopenharmony_ci
227cabdff1aSopenharmony_ci    s->bpp = avctx->bits_per_coded_sample >> 3;
228cabdff1aSopenharmony_ci    stride = 4 * ((avctx->width * avctx->bits_per_coded_sample + 31) / 32);
229cabdff1aSopenharmony_ci
230cabdff1aSopenharmony_ci    s->decomp_size = 2 * avctx->height * stride;
231cabdff1aSopenharmony_ci    if (!(s->decomp_buf = av_malloc(s->decomp_size)))
232cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
233cabdff1aSopenharmony_ci
234cabdff1aSopenharmony_ci    s->uncomp_size = avctx->height * stride;
235cabdff1aSopenharmony_ci    if (!(s->uncomp_buf = av_malloc(s->uncomp_size)))
236cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
237cabdff1aSopenharmony_ci
238cabdff1aSopenharmony_ci    return ff_inflate_init(&s->zstream, avctx);
239cabdff1aSopenharmony_ci}
240cabdff1aSopenharmony_ci
241cabdff1aSopenharmony_cistatic av_cold int decode_close(AVCodecContext *avctx)
242cabdff1aSopenharmony_ci{
243cabdff1aSopenharmony_ci    MSCCContext *s = avctx->priv_data;
244cabdff1aSopenharmony_ci
245cabdff1aSopenharmony_ci    av_freep(&s->decomp_buf);
246cabdff1aSopenharmony_ci    s->decomp_size = 0;
247cabdff1aSopenharmony_ci    av_freep(&s->uncomp_buf);
248cabdff1aSopenharmony_ci    s->uncomp_size = 0;
249cabdff1aSopenharmony_ci    ff_inflate_end(&s->zstream);
250cabdff1aSopenharmony_ci
251cabdff1aSopenharmony_ci    return 0;
252cabdff1aSopenharmony_ci}
253cabdff1aSopenharmony_ci
254cabdff1aSopenharmony_ciconst FFCodec ff_mscc_decoder = {
255cabdff1aSopenharmony_ci    .p.name           = "mscc",
256cabdff1aSopenharmony_ci    .p.long_name      = NULL_IF_CONFIG_SMALL("Mandsoft Screen Capture Codec"),
257cabdff1aSopenharmony_ci    .p.type           = AVMEDIA_TYPE_VIDEO,
258cabdff1aSopenharmony_ci    .p.id             = AV_CODEC_ID_MSCC,
259cabdff1aSopenharmony_ci    .priv_data_size   = sizeof(MSCCContext),
260cabdff1aSopenharmony_ci    .init             = decode_init,
261cabdff1aSopenharmony_ci    .close            = decode_close,
262cabdff1aSopenharmony_ci    FF_CODEC_DECODE_CB(decode_frame),
263cabdff1aSopenharmony_ci    .p.capabilities   = AV_CODEC_CAP_DR1,
264cabdff1aSopenharmony_ci    .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
265cabdff1aSopenharmony_ci};
266cabdff1aSopenharmony_ci
267cabdff1aSopenharmony_ciconst FFCodec ff_srgc_decoder = {
268cabdff1aSopenharmony_ci    .p.name           = "srgc",
269cabdff1aSopenharmony_ci    .p.long_name      = NULL_IF_CONFIG_SMALL("Screen Recorder Gold Codec"),
270cabdff1aSopenharmony_ci    .p.type           = AVMEDIA_TYPE_VIDEO,
271cabdff1aSopenharmony_ci    .p.id             = AV_CODEC_ID_SRGC,
272cabdff1aSopenharmony_ci    .priv_data_size   = sizeof(MSCCContext),
273cabdff1aSopenharmony_ci    .init             = decode_init,
274cabdff1aSopenharmony_ci    .close            = decode_close,
275cabdff1aSopenharmony_ci    FF_CODEC_DECODE_CB(decode_frame),
276cabdff1aSopenharmony_ci    .p.capabilities   = AV_CODEC_CAP_DR1,
277cabdff1aSopenharmony_ci    .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
278cabdff1aSopenharmony_ci};
279