• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
30 typedef struct RangeCoder {
31     uint32_t   code;
32     uint32_t   range;
33     uint32_t   code1;
34 } RangeCoder;
35 
36 typedef struct PixelModel {
37     uint32_t    freq[256];
38     uint32_t    lookup[16];
39     uint32_t    total_freq;
40 } PixelModel;
41 
42 typedef 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 
decode_run_i(AVCodecContext * avctx,uint32_t ptype,int run,int * px,int * py,uint32_t clr,uint32_t * dst,int linesize,uint32_t * plx,uint32_t * ply,uint32_t backstep,int off,int * cx,int * cx1)75 static 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 
decode_run_p(AVCodecContext * avctx,uint32_t ptype,int run,int x,int y,uint32_t clr,uint32_t * dst,uint32_t * prev,int linesize,int plinesize,uint32_t * bx,uint32_t * by,uint32_t backstep,int sx1,int sx2,int * cx,int * cx1)217 static 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