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