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