1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * ScreenPressor 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#ifndef AVCODEC_SCPR_H
24cabdff1aSopenharmony_ci#define AVCODEC_SCPR_H
25cabdff1aSopenharmony_ci
26cabdff1aSopenharmony_ci#include "avcodec.h"
27cabdff1aSopenharmony_ci#include "bytestream.h"
28cabdff1aSopenharmony_ci#include "scpr3.h"
29cabdff1aSopenharmony_ci
30cabdff1aSopenharmony_citypedef struct RangeCoder {
31cabdff1aSopenharmony_ci    uint32_t   code;
32cabdff1aSopenharmony_ci    uint32_t   range;
33cabdff1aSopenharmony_ci    uint32_t   code1;
34cabdff1aSopenharmony_ci} RangeCoder;
35cabdff1aSopenharmony_ci
36cabdff1aSopenharmony_citypedef struct PixelModel {
37cabdff1aSopenharmony_ci    uint32_t    freq[256];
38cabdff1aSopenharmony_ci    uint32_t    lookup[16];
39cabdff1aSopenharmony_ci    uint32_t    total_freq;
40cabdff1aSopenharmony_ci} PixelModel;
41cabdff1aSopenharmony_ci
42cabdff1aSopenharmony_citypedef struct SCPRContext {
43cabdff1aSopenharmony_ci    int             version;
44cabdff1aSopenharmony_ci    AVFrame        *last_frame;
45cabdff1aSopenharmony_ci    AVFrame        *current_frame;
46cabdff1aSopenharmony_ci    GetByteContext  gb;
47cabdff1aSopenharmony_ci    RangeCoder      rc;
48cabdff1aSopenharmony_ci    PixelModel      pixel_model[3][4096];
49cabdff1aSopenharmony_ci    uint32_t        op_model[6][7];
50cabdff1aSopenharmony_ci    uint32_t        run_model[6][257];
51cabdff1aSopenharmony_ci    uint32_t        range_model[257];
52cabdff1aSopenharmony_ci    uint32_t        count_model[257];
53cabdff1aSopenharmony_ci    uint32_t        fill_model[6];
54cabdff1aSopenharmony_ci    uint32_t        sxy_model[4][17];
55cabdff1aSopenharmony_ci    uint32_t        mv_model[2][513];
56cabdff1aSopenharmony_ci    uint32_t        nbx, nby;
57cabdff1aSopenharmony_ci    uint32_t        nbcount;
58cabdff1aSopenharmony_ci    uint32_t       *blocks;
59cabdff1aSopenharmony_ci    uint32_t        cbits;
60cabdff1aSopenharmony_ci    int             cxshift;
61cabdff1aSopenharmony_ci
62cabdff1aSopenharmony_ci    PixelModel3     pixel_model3[3][4096];
63cabdff1aSopenharmony_ci    RunModel3       run_model3[6];
64cabdff1aSopenharmony_ci    RunModel3       range_model3;
65cabdff1aSopenharmony_ci    RunModel3       count_model3;
66cabdff1aSopenharmony_ci    FillModel3      fill_model3;
67cabdff1aSopenharmony_ci    SxyModel3       sxy_model3[4];
68cabdff1aSopenharmony_ci    MVModel3        mv_model3[2];
69cabdff1aSopenharmony_ci    OpModel3        op_model3[6];
70cabdff1aSopenharmony_ci
71cabdff1aSopenharmony_ci    int           (*get_freq)(RangeCoder *rc, uint32_t total_freq, uint32_t *freq);
72cabdff1aSopenharmony_ci    int           (*decode)(GetByteContext *gb, RangeCoder *rc, uint32_t cumFreq, uint32_t freq, uint32_t total_freq);
73cabdff1aSopenharmony_ci} SCPRContext;
74cabdff1aSopenharmony_ci
75cabdff1aSopenharmony_cistatic int decode_run_i(AVCodecContext *avctx, uint32_t ptype, int run,
76cabdff1aSopenharmony_ci                        int *px, int *py, uint32_t clr, uint32_t *dst,
77cabdff1aSopenharmony_ci                        int linesize, uint32_t *plx, uint32_t *ply,
78cabdff1aSopenharmony_ci                        uint32_t backstep, int off, int *cx, int *cx1)
79cabdff1aSopenharmony_ci{
80cabdff1aSopenharmony_ci    uint32_t r, g, b;
81cabdff1aSopenharmony_ci    int z;
82cabdff1aSopenharmony_ci    int x = *px,
83cabdff1aSopenharmony_ci        y = *py;
84cabdff1aSopenharmony_ci    uint32_t lx = *plx,
85cabdff1aSopenharmony_ci             ly = *ply;
86cabdff1aSopenharmony_ci
87cabdff1aSopenharmony_ci    if (y >= avctx->height)
88cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
89cabdff1aSopenharmony_ci
90cabdff1aSopenharmony_ci    switch (ptype) {
91cabdff1aSopenharmony_ci    case 0:
92cabdff1aSopenharmony_ci        while (run-- > 0) {
93cabdff1aSopenharmony_ci            dst[y * linesize + x] = clr;
94cabdff1aSopenharmony_ci            lx = x;
95cabdff1aSopenharmony_ci            ly = y;
96cabdff1aSopenharmony_ci            (x)++;
97cabdff1aSopenharmony_ci            if (x >= avctx->width) {
98cabdff1aSopenharmony_ci                x = 0;
99cabdff1aSopenharmony_ci                (y)++;
100cabdff1aSopenharmony_ci                if (y >= avctx->height && run)
101cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
102cabdff1aSopenharmony_ci            }
103cabdff1aSopenharmony_ci        }
104cabdff1aSopenharmony_ci        break;
105cabdff1aSopenharmony_ci    case 1:
106cabdff1aSopenharmony_ci        while (run-- > 0) {
107cabdff1aSopenharmony_ci            dst[y * linesize + x] = dst[ly * linesize + lx];
108cabdff1aSopenharmony_ci            lx = x;
109cabdff1aSopenharmony_ci            ly = y;
110cabdff1aSopenharmony_ci            (x)++;
111cabdff1aSopenharmony_ci            if (x >= avctx->width) {
112cabdff1aSopenharmony_ci                x = 0;
113cabdff1aSopenharmony_ci                (y)++;
114cabdff1aSopenharmony_ci                if (y >= avctx->height && run)
115cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
116cabdff1aSopenharmony_ci            }
117cabdff1aSopenharmony_ci        }
118cabdff1aSopenharmony_ci        clr = dst[ly * linesize + lx];
119cabdff1aSopenharmony_ci        break;
120cabdff1aSopenharmony_ci    case 2:
121cabdff1aSopenharmony_ci        if (y < 1)
122cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
123cabdff1aSopenharmony_ci
124cabdff1aSopenharmony_ci        while (run-- > 0) {
125cabdff1aSopenharmony_ci            clr = dst[y * linesize + x + off + 1];
126cabdff1aSopenharmony_ci            dst[y * linesize + x] = clr;
127cabdff1aSopenharmony_ci            lx = x;
128cabdff1aSopenharmony_ci            ly = y;
129cabdff1aSopenharmony_ci            (x)++;
130cabdff1aSopenharmony_ci            if (x >= avctx->width) {
131cabdff1aSopenharmony_ci                x = 0;
132cabdff1aSopenharmony_ci                (y)++;
133cabdff1aSopenharmony_ci                if (y >= avctx->height && run)
134cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
135cabdff1aSopenharmony_ci            }
136cabdff1aSopenharmony_ci        }
137cabdff1aSopenharmony_ci        break;
138cabdff1aSopenharmony_ci    case 4:
139cabdff1aSopenharmony_ci        if (y < 1 || (y == 1 && x == 0))
140cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
141cabdff1aSopenharmony_ci
142cabdff1aSopenharmony_ci        while (run-- > 0) {
143cabdff1aSopenharmony_ci            uint8_t *odst = (uint8_t *)dst;
144cabdff1aSopenharmony_ci            int off1 = (ly * linesize + lx) * 4;
145cabdff1aSopenharmony_ci            int off2 = ((y * linesize + x) + off) * 4;
146cabdff1aSopenharmony_ci
147cabdff1aSopenharmony_ci            if (x == 0) {
148cabdff1aSopenharmony_ci                z = backstep * 4;
149cabdff1aSopenharmony_ci            } else {
150cabdff1aSopenharmony_ci                z = 0;
151cabdff1aSopenharmony_ci            }
152cabdff1aSopenharmony_ci
153cabdff1aSopenharmony_ci            r = odst[off1] +
154cabdff1aSopenharmony_ci                odst[off2 + 4] -
155cabdff1aSopenharmony_ci                odst[off2 - z ];
156cabdff1aSopenharmony_ci            g = odst[off1 + 1] +
157cabdff1aSopenharmony_ci                odst[off2 + 5] -
158cabdff1aSopenharmony_ci                odst[off2 - z  + 1];
159cabdff1aSopenharmony_ci            b = odst[off1 + 2] +
160cabdff1aSopenharmony_ci                odst[off2 + 6] -
161cabdff1aSopenharmony_ci                odst[off2 - z  + 2];
162cabdff1aSopenharmony_ci            clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8) + (r & 0xFF);
163cabdff1aSopenharmony_ci            dst[y * linesize + x] = clr;
164cabdff1aSopenharmony_ci            lx = x;
165cabdff1aSopenharmony_ci            ly = y;
166cabdff1aSopenharmony_ci            (x)++;
167cabdff1aSopenharmony_ci            if (x >= avctx->width) {
168cabdff1aSopenharmony_ci                x = 0;
169cabdff1aSopenharmony_ci                (y)++;
170cabdff1aSopenharmony_ci                if (y >= avctx->height && run)
171cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
172cabdff1aSopenharmony_ci            }
173cabdff1aSopenharmony_ci        }
174cabdff1aSopenharmony_ci        break;
175cabdff1aSopenharmony_ci    case 5:
176cabdff1aSopenharmony_ci        if (y < 1 || (y == 1 && x == 0))
177cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
178cabdff1aSopenharmony_ci
179cabdff1aSopenharmony_ci        while (run-- > 0) {
180cabdff1aSopenharmony_ci            if (x == 0) {
181cabdff1aSopenharmony_ci                z = backstep;
182cabdff1aSopenharmony_ci            } else {
183cabdff1aSopenharmony_ci                z = 0;
184cabdff1aSopenharmony_ci            }
185cabdff1aSopenharmony_ci
186cabdff1aSopenharmony_ci            clr = dst[y * linesize + x + off - z];
187cabdff1aSopenharmony_ci            dst[y * linesize + x] = clr;
188cabdff1aSopenharmony_ci            lx = x;
189cabdff1aSopenharmony_ci            ly = y;
190cabdff1aSopenharmony_ci            (x)++;
191cabdff1aSopenharmony_ci            if (x >= avctx->width) {
192cabdff1aSopenharmony_ci                x = 0;
193cabdff1aSopenharmony_ci                (y)++;
194cabdff1aSopenharmony_ci                if (y >= avctx->height && run)
195cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
196cabdff1aSopenharmony_ci            }
197cabdff1aSopenharmony_ci        }
198cabdff1aSopenharmony_ci        break;
199cabdff1aSopenharmony_ci    }
200cabdff1aSopenharmony_ci
201cabdff1aSopenharmony_ci    *px = x;
202cabdff1aSopenharmony_ci    *py = y;
203cabdff1aSopenharmony_ci    *plx= lx;
204cabdff1aSopenharmony_ci    *ply= ly;
205cabdff1aSopenharmony_ci
206cabdff1aSopenharmony_ci    if (avctx->bits_per_coded_sample == 16) {
207cabdff1aSopenharmony_ci        *cx1 = (clr & 0x3F00) >> 2;
208cabdff1aSopenharmony_ci        *cx = (clr & 0x3FFFFF) >> 16;
209cabdff1aSopenharmony_ci    } else {
210cabdff1aSopenharmony_ci        *cx1 = (clr & 0xFC00) >> 4;
211cabdff1aSopenharmony_ci        *cx = (clr & 0xFFFFFF) >> 18;
212cabdff1aSopenharmony_ci    }
213cabdff1aSopenharmony_ci
214cabdff1aSopenharmony_ci    return 0;
215cabdff1aSopenharmony_ci}
216cabdff1aSopenharmony_ci
217cabdff1aSopenharmony_cistatic int decode_run_p(AVCodecContext *avctx, uint32_t ptype, int run,
218cabdff1aSopenharmony_ci                        int x, int y, uint32_t clr,
219cabdff1aSopenharmony_ci                        uint32_t *dst, uint32_t *prev,
220cabdff1aSopenharmony_ci                        int linesize, int plinesize,
221cabdff1aSopenharmony_ci                        uint32_t *bx, uint32_t *by,
222cabdff1aSopenharmony_ci                        uint32_t backstep, int sx1, int sx2,
223cabdff1aSopenharmony_ci                        int *cx, int *cx1)
224cabdff1aSopenharmony_ci{
225cabdff1aSopenharmony_ci    uint32_t r, g, b;
226cabdff1aSopenharmony_ci    int z;
227cabdff1aSopenharmony_ci
228cabdff1aSopenharmony_ci    switch (ptype) {
229cabdff1aSopenharmony_ci    case 0:
230cabdff1aSopenharmony_ci        while (run-- > 0) {
231cabdff1aSopenharmony_ci            if (*by >= avctx->height)
232cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
233cabdff1aSopenharmony_ci
234cabdff1aSopenharmony_ci            dst[*by * linesize + *bx] = clr;
235cabdff1aSopenharmony_ci            (*bx)++;
236cabdff1aSopenharmony_ci            if (*bx >= x * 16 + sx2 || *bx >= avctx->width) {
237cabdff1aSopenharmony_ci                *bx = x * 16 + sx1;
238cabdff1aSopenharmony_ci                (*by)++;
239cabdff1aSopenharmony_ci            }
240cabdff1aSopenharmony_ci        }
241cabdff1aSopenharmony_ci        break;
242cabdff1aSopenharmony_ci    case 1:
243cabdff1aSopenharmony_ci        while (run-- > 0) {
244cabdff1aSopenharmony_ci            if (*bx == 0) {
245cabdff1aSopenharmony_ci                if (*by < 1)
246cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
247cabdff1aSopenharmony_ci                z = backstep;
248cabdff1aSopenharmony_ci            } else {
249cabdff1aSopenharmony_ci                z = 0;
250cabdff1aSopenharmony_ci            }
251cabdff1aSopenharmony_ci
252cabdff1aSopenharmony_ci            if (*by >= avctx->height)
253cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
254cabdff1aSopenharmony_ci
255cabdff1aSopenharmony_ci            clr = dst[*by * linesize + *bx - 1 - z];
256cabdff1aSopenharmony_ci            dst[*by * linesize + *bx] = clr;
257cabdff1aSopenharmony_ci            (*bx)++;
258cabdff1aSopenharmony_ci            if (*bx >= x * 16 + sx2 || *bx >= avctx->width) {
259cabdff1aSopenharmony_ci                *bx = x * 16 + sx1;
260cabdff1aSopenharmony_ci                (*by)++;
261cabdff1aSopenharmony_ci            }
262cabdff1aSopenharmony_ci        }
263cabdff1aSopenharmony_ci        break;
264cabdff1aSopenharmony_ci    case 2:
265cabdff1aSopenharmony_ci        while (run-- > 0) {
266cabdff1aSopenharmony_ci            if (*by < 1 || *by >= avctx->height)
267cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
268cabdff1aSopenharmony_ci
269cabdff1aSopenharmony_ci            clr = dst[(*by - 1) * linesize + *bx];
270cabdff1aSopenharmony_ci            dst[*by * linesize + *bx] = clr;
271cabdff1aSopenharmony_ci            (*bx)++;
272cabdff1aSopenharmony_ci            if (*bx >= x * 16 + sx2 || *bx >= avctx->width) {
273cabdff1aSopenharmony_ci                *bx = x * 16 + sx1;
274cabdff1aSopenharmony_ci                (*by)++;
275cabdff1aSopenharmony_ci            }
276cabdff1aSopenharmony_ci        }
277cabdff1aSopenharmony_ci        break;
278cabdff1aSopenharmony_ci    case 3:
279cabdff1aSopenharmony_ci        while (run-- > 0) {
280cabdff1aSopenharmony_ci            if (*by >= avctx->height)
281cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
282cabdff1aSopenharmony_ci
283cabdff1aSopenharmony_ci            clr = prev[*by * plinesize + *bx];
284cabdff1aSopenharmony_ci            dst[*by * linesize + *bx] = clr;
285cabdff1aSopenharmony_ci            (*bx)++;
286cabdff1aSopenharmony_ci            if (*bx >= x * 16 + sx2 || *bx >= avctx->width) {
287cabdff1aSopenharmony_ci                *bx = x * 16 + sx1;
288cabdff1aSopenharmony_ci                (*by)++;
289cabdff1aSopenharmony_ci            }
290cabdff1aSopenharmony_ci        }
291cabdff1aSopenharmony_ci        break;
292cabdff1aSopenharmony_ci    case 4:
293cabdff1aSopenharmony_ci        while (run-- > 0) {
294cabdff1aSopenharmony_ci            uint8_t *odst = (uint8_t *)dst;
295cabdff1aSopenharmony_ci
296cabdff1aSopenharmony_ci            if (*by < 1 || *by >= avctx->height)
297cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
298cabdff1aSopenharmony_ci
299cabdff1aSopenharmony_ci            if (*bx == 0) {
300cabdff1aSopenharmony_ci                if (*by < 2)
301cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
302cabdff1aSopenharmony_ci                z = backstep;
303cabdff1aSopenharmony_ci            } else {
304cabdff1aSopenharmony_ci                z = 0;
305cabdff1aSopenharmony_ci            }
306cabdff1aSopenharmony_ci
307cabdff1aSopenharmony_ci            r = odst[((*by - 1) * linesize + *bx) * 4] +
308cabdff1aSopenharmony_ci                odst[(*by * linesize + *bx - 1 - z) * 4] -
309cabdff1aSopenharmony_ci                odst[((*by - 1) * linesize + *bx - 1 - z) * 4];
310cabdff1aSopenharmony_ci            g = odst[((*by - 1) * linesize + *bx) * 4 + 1] +
311cabdff1aSopenharmony_ci                odst[(*by * linesize + *bx - 1 - z) * 4 + 1] -
312cabdff1aSopenharmony_ci                odst[((*by - 1) * linesize + *bx - 1 - z) * 4 + 1];
313cabdff1aSopenharmony_ci            b = odst[((*by - 1) * linesize + *bx) * 4 + 2] +
314cabdff1aSopenharmony_ci                odst[(*by * linesize + *bx - 1 - z) * 4 + 2] -
315cabdff1aSopenharmony_ci                odst[((*by - 1) * linesize + *bx - 1 - z) * 4 + 2];
316cabdff1aSopenharmony_ci            clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8) + (r & 0xFF);
317cabdff1aSopenharmony_ci            dst[*by * linesize + *bx] = clr;
318cabdff1aSopenharmony_ci            (*bx)++;
319cabdff1aSopenharmony_ci            if (*bx >= x * 16 + sx2 || *bx >= avctx->width) {
320cabdff1aSopenharmony_ci                *bx = x * 16 + sx1;
321cabdff1aSopenharmony_ci                (*by)++;
322cabdff1aSopenharmony_ci            }
323cabdff1aSopenharmony_ci        }
324cabdff1aSopenharmony_ci        break;
325cabdff1aSopenharmony_ci    case 5:
326cabdff1aSopenharmony_ci        while (run-- > 0) {
327cabdff1aSopenharmony_ci            if (*by < 1 || *by >= avctx->height)
328cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
329cabdff1aSopenharmony_ci
330cabdff1aSopenharmony_ci            if (*bx == 0) {
331cabdff1aSopenharmony_ci                if (*by < 2)
332cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
333cabdff1aSopenharmony_ci                z = backstep;
334cabdff1aSopenharmony_ci            } else {
335cabdff1aSopenharmony_ci                z = 0;
336cabdff1aSopenharmony_ci            }
337cabdff1aSopenharmony_ci
338cabdff1aSopenharmony_ci            clr = dst[(*by - 1) * linesize + *bx - 1 - z];
339cabdff1aSopenharmony_ci            dst[*by * linesize + *bx] = clr;
340cabdff1aSopenharmony_ci            (*bx)++;
341cabdff1aSopenharmony_ci            if (*bx >= x * 16 + sx2 || *bx >= avctx->width) {
342cabdff1aSopenharmony_ci                *bx = x * 16 + sx1;
343cabdff1aSopenharmony_ci                (*by)++;
344cabdff1aSopenharmony_ci            }
345cabdff1aSopenharmony_ci        }
346cabdff1aSopenharmony_ci        break;
347cabdff1aSopenharmony_ci    }
348cabdff1aSopenharmony_ci
349cabdff1aSopenharmony_ci    if (avctx->bits_per_coded_sample == 16) {
350cabdff1aSopenharmony_ci        *cx1 = (clr & 0x3F00) >> 2;
351cabdff1aSopenharmony_ci        *cx = (clr & 0x3FFFFF) >> 16;
352cabdff1aSopenharmony_ci    } else {
353cabdff1aSopenharmony_ci        *cx1 = (clr & 0xFC00) >> 4;
354cabdff1aSopenharmony_ci        *cx = (clr & 0xFFFFFF) >> 18;
355cabdff1aSopenharmony_ci    }
356cabdff1aSopenharmony_ci
357cabdff1aSopenharmony_ci    return 0;
358cabdff1aSopenharmony_ci}
359cabdff1aSopenharmony_ci
360cabdff1aSopenharmony_ci#endif /* AVCODEC_SCPR_H */
361