/src/ffmpeg/libavcodec/scpr.h
Line | Count | Source |
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 | | |
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 | 1.10M | { |
80 | 1.10M | uint32_t r, g, b; |
81 | 1.10M | int z; |
82 | 1.10M | int x = *px, |
83 | 1.10M | y = *py; |
84 | 1.10M | uint32_t lx = *plx, |
85 | 1.10M | ly = *ply; |
86 | | |
87 | 1.10M | if (y >= avctx->height) |
88 | 0 | return AVERROR_INVALIDDATA; |
89 | | |
90 | 1.10M | switch (ptype) { |
91 | 68.4k | case 0: |
92 | 7.81M | while (run-- > 0) { |
93 | 7.74M | dst[y * linesize + x] = clr; |
94 | 7.74M | lx = x; |
95 | 7.74M | ly = y; |
96 | 7.74M | (x)++; |
97 | 7.74M | if (x >= avctx->width) { |
98 | 434k | x = 0; |
99 | 434k | (y)++; |
100 | 434k | if (y >= avctx->height && run) |
101 | 357 | return AVERROR_INVALIDDATA; |
102 | 434k | } |
103 | 7.74M | } |
104 | 68.1k | break; |
105 | 126k | case 1: |
106 | 16.9M | while (run-- > 0) { |
107 | 16.7M | dst[y * linesize + x] = dst[ly * linesize + lx]; |
108 | 16.7M | lx = x; |
109 | 16.7M | ly = y; |
110 | 16.7M | (x)++; |
111 | 16.7M | if (x >= avctx->width) { |
112 | 437k | x = 0; |
113 | 437k | (y)++; |
114 | 437k | if (y >= avctx->height && run) |
115 | 515 | return AVERROR_INVALIDDATA; |
116 | 437k | } |
117 | 16.7M | } |
118 | 125k | clr = dst[ly * linesize + lx]; |
119 | 125k | break; |
120 | 103k | case 2: |
121 | 103k | if (y < 1) |
122 | 0 | return AVERROR_INVALIDDATA; |
123 | | |
124 | 12.6M | while (run-- > 0) { |
125 | 12.5M | clr = dst[y * linesize + x + off + 1]; |
126 | 12.5M | dst[y * linesize + x] = clr; |
127 | 12.5M | lx = x; |
128 | 12.5M | ly = y; |
129 | 12.5M | (x)++; |
130 | 12.5M | if (x >= avctx->width) { |
131 | 841k | x = 0; |
132 | 841k | (y)++; |
133 | 841k | if (y >= avctx->height && run) |
134 | 457 | return AVERROR_INVALIDDATA; |
135 | 841k | } |
136 | 12.5M | } |
137 | 102k | break; |
138 | 112k | case 4: |
139 | 112k | if (y < 1 || (y == 1 && x == 0)) |
140 | 0 | return AVERROR_INVALIDDATA; |
141 | | |
142 | 11.0M | while (run-- > 0) { |
143 | 10.8M | uint8_t *odst = (uint8_t *)dst; |
144 | 10.8M | int off1 = (ly * linesize + lx) * 4; |
145 | 10.8M | int off2 = ((y * linesize + x) + off) * 4; |
146 | | |
147 | 10.8M | if (x == 0) { |
148 | 1.35M | z = backstep * 4; |
149 | 9.53M | } else { |
150 | 9.53M | z = 0; |
151 | 9.53M | } |
152 | | |
153 | 10.8M | r = odst[off1] + |
154 | 10.8M | odst[off2 + 4] - |
155 | 10.8M | odst[off2 - z ]; |
156 | 10.8M | g = odst[off1 + 1] + |
157 | 10.8M | odst[off2 + 5] - |
158 | 10.8M | odst[off2 - z + 1]; |
159 | 10.8M | b = odst[off1 + 2] + |
160 | 10.8M | odst[off2 + 6] - |
161 | 10.8M | odst[off2 - z + 2]; |
162 | 10.8M | clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8) + (r & 0xFF); |
163 | 10.8M | dst[y * linesize + x] = clr; |
164 | 10.8M | lx = x; |
165 | 10.8M | ly = y; |
166 | 10.8M | (x)++; |
167 | 10.8M | if (x >= avctx->width) { |
168 | 1.35M | x = 0; |
169 | 1.35M | (y)++; |
170 | 1.35M | if (y >= avctx->height && run) |
171 | 308 | return AVERROR_INVALIDDATA; |
172 | 1.35M | } |
173 | 10.8M | } |
174 | 112k | break; |
175 | 494k | case 5: |
176 | 494k | if (y < 1 || (y == 1 && x == 0)) |
177 | 0 | return AVERROR_INVALIDDATA; |
178 | | |
179 | 105M | while (run-- > 0) { |
180 | 105M | if (x == 0) { |
181 | 3.95M | z = backstep; |
182 | 101M | } else { |
183 | 101M | z = 0; |
184 | 101M | } |
185 | | |
186 | 105M | clr = dst[y * linesize + x + off - z]; |
187 | 105M | dst[y * linesize + x] = clr; |
188 | 105M | lx = x; |
189 | 105M | ly = y; |
190 | 105M | (x)++; |
191 | 105M | if (x >= avctx->width) { |
192 | 3.96M | x = 0; |
193 | 3.96M | (y)++; |
194 | 3.96M | if (y >= avctx->height && run) |
195 | 534 | return AVERROR_INVALIDDATA; |
196 | 3.96M | } |
197 | 105M | } |
198 | 494k | break; |
199 | 1.10M | } |
200 | | |
201 | 1.10M | *px = x; |
202 | 1.10M | *py = y; |
203 | 1.10M | *plx= lx; |
204 | 1.10M | *ply= ly; |
205 | | |
206 | 1.10M | if (avctx->bits_per_coded_sample == 16) { |
207 | 570k | *cx1 = (clr & 0x3F00) >> 2; |
208 | 570k | *cx = (clr & 0x3FFFFF) >> 16; |
209 | 570k | } else { |
210 | 530k | *cx1 = (clr & 0xFC00) >> 4; |
211 | 530k | *cx = (clr & 0xFFFFFF) >> 18; |
212 | 530k | } |
213 | | |
214 | 1.10M | return 0; |
215 | 1.10M | } |
216 | | |
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 | 951k | { |
225 | 951k | uint32_t r, g, b; |
226 | 951k | int z; |
227 | | |
228 | 951k | switch (ptype) { |
229 | 249k | case 0: |
230 | 20.0M | while (run-- > 0) { |
231 | 19.8M | if (*by >= avctx->height) |
232 | 1.83k | return AVERROR_INVALIDDATA; |
233 | | |
234 | 19.8M | dst[*by * linesize + *bx] = clr; |
235 | 19.8M | (*bx)++; |
236 | 19.8M | if (*bx >= x * 16 + sx2 || *bx >= avctx->width) { |
237 | 5.17M | *bx = x * 16 + sx1; |
238 | 5.17M | (*by)++; |
239 | 5.17M | } |
240 | 19.8M | } |
241 | 248k | break; |
242 | 248k | case 1: |
243 | 11.5M | while (run-- > 0) { |
244 | 11.4M | if (*bx == 0) { |
245 | 68.8k | if (*by < 1) |
246 | 545 | return AVERROR_INVALIDDATA; |
247 | 68.3k | z = backstep; |
248 | 11.3M | } else { |
249 | 11.3M | z = 0; |
250 | 11.3M | } |
251 | | |
252 | 11.4M | if (*by >= avctx->height) |
253 | 1.21k | return AVERROR_INVALIDDATA; |
254 | | |
255 | 11.4M | clr = dst[*by * linesize + *bx - 1 - z]; |
256 | 11.4M | dst[*by * linesize + *bx] = clr; |
257 | 11.4M | (*bx)++; |
258 | 11.4M | if (*bx >= x * 16 + sx2 || *bx >= avctx->width) { |
259 | 2.90M | *bx = x * 16 + sx1; |
260 | 2.90M | (*by)++; |
261 | 2.90M | } |
262 | 11.4M | } |
263 | 86.8k | break; |
264 | 205k | case 2: |
265 | 18.5M | while (run-- > 0) { |
266 | 18.3M | if (*by < 1 || *by >= avctx->height) |
267 | 1.61k | return AVERROR_INVALIDDATA; |
268 | | |
269 | 18.3M | clr = dst[(*by - 1) * linesize + *bx]; |
270 | 18.3M | dst[*by * linesize + *bx] = clr; |
271 | 18.3M | (*bx)++; |
272 | 18.3M | if (*bx >= x * 16 + sx2 || *bx >= avctx->width) { |
273 | 3.76M | *bx = x * 16 + sx1; |
274 | 3.76M | (*by)++; |
275 | 3.76M | } |
276 | 18.3M | } |
277 | 203k | break; |
278 | 251k | case 3: |
279 | 22.7M | while (run-- > 0) { |
280 | 22.5M | if (*by >= avctx->height) |
281 | 1.43k | return AVERROR_INVALIDDATA; |
282 | | |
283 | 22.5M | clr = prev[*by * plinesize + *bx]; |
284 | 22.5M | dst[*by * linesize + *bx] = clr; |
285 | 22.5M | (*bx)++; |
286 | 22.5M | if (*bx >= x * 16 + sx2 || *bx >= avctx->width) { |
287 | 4.86M | *bx = x * 16 + sx1; |
288 | 4.86M | (*by)++; |
289 | 4.86M | } |
290 | 22.5M | } |
291 | 250k | break; |
292 | 250k | case 4: |
293 | 7.21M | while (run-- > 0) { |
294 | 7.15M | uint8_t *odst = (uint8_t *)dst; |
295 | | |
296 | 7.15M | if (*by < 1 || *by >= avctx->height) |
297 | 2.40k | return AVERROR_INVALIDDATA; |
298 | | |
299 | 7.15M | if (*bx == 0) { |
300 | 44.1k | if (*by < 2) |
301 | 196 | return AVERROR_INVALIDDATA; |
302 | 43.9k | z = backstep; |
303 | 7.11M | } else { |
304 | 7.11M | z = 0; |
305 | 7.11M | } |
306 | | |
307 | 7.15M | r = odst[((*by - 1) * linesize + *bx) * 4] + |
308 | 7.15M | odst[(*by * linesize + *bx - 1 - z) * 4] - |
309 | 7.15M | odst[((*by - 1) * linesize + *bx - 1 - z) * 4]; |
310 | 7.15M | g = odst[((*by - 1) * linesize + *bx) * 4 + 1] + |
311 | 7.15M | odst[(*by * linesize + *bx - 1 - z) * 4 + 1] - |
312 | 7.15M | odst[((*by - 1) * linesize + *bx - 1 - z) * 4 + 1]; |
313 | 7.15M | b = odst[((*by - 1) * linesize + *bx) * 4 + 2] + |
314 | 7.15M | odst[(*by * linesize + *bx - 1 - z) * 4 + 2] - |
315 | 7.15M | odst[((*by - 1) * linesize + *bx - 1 - z) * 4 + 2]; |
316 | 7.15M | clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8) + (r & 0xFF); |
317 | 7.15M | dst[*by * linesize + *bx] = clr; |
318 | 7.15M | (*bx)++; |
319 | 7.15M | if (*bx >= x * 16 + sx2 || *bx >= avctx->width) { |
320 | 2.56M | *bx = x * 16 + sx1; |
321 | 2.56M | (*by)++; |
322 | 2.56M | } |
323 | 7.15M | } |
324 | 53.9k | break; |
325 | 98.8k | case 5: |
326 | 12.7M | while (run-- > 0) { |
327 | 12.6M | if (*by < 1 || *by >= avctx->height) |
328 | 3.55k | return AVERROR_INVALIDDATA; |
329 | | |
330 | 12.6M | if (*bx == 0) { |
331 | 497k | if (*by < 2) |
332 | 196 | return AVERROR_INVALIDDATA; |
333 | 496k | z = backstep; |
334 | 12.1M | } else { |
335 | 12.1M | z = 0; |
336 | 12.1M | } |
337 | | |
338 | 12.6M | clr = dst[(*by - 1) * linesize + *bx - 1 - z]; |
339 | 12.6M | dst[*by * linesize + *bx] = clr; |
340 | 12.6M | (*bx)++; |
341 | 12.6M | if (*bx >= x * 16 + sx2 || *bx >= avctx->width) { |
342 | 4.55M | *bx = x * 16 + sx1; |
343 | 4.55M | (*by)++; |
344 | 4.55M | } |
345 | 12.6M | } |
346 | 95.1k | break; |
347 | 951k | } |
348 | | |
349 | 938k | if (avctx->bits_per_coded_sample == 16) { |
350 | 498k | *cx1 = (clr & 0x3F00) >> 2; |
351 | 498k | *cx = (clr & 0x3FFFFF) >> 16; |
352 | 498k | } else { |
353 | 439k | *cx1 = (clr & 0xFC00) >> 4; |
354 | 439k | *cx = (clr & 0xFFFFFF) >> 18; |
355 | 439k | } |
356 | | |
357 | 938k | return 0; |
358 | 951k | } |
359 | | |
360 | | #endif /* AVCODEC_SCPR_H */ |