FFmpeg
sanm.c
Go to the documentation of this file.
1 /*
2  * LucasArts Smush video decoder
3  * Copyright (c) 2006 Cyril Zorin
4  * Copyright (c) 2011 Konstantin Shishkov
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 #include "libavutil/avassert.h"
24 #include "libavutil/mem.h"
25 
26 #include "avcodec.h"
27 #include "bytestream.h"
28 #include "copy_block.h"
29 #include "codec_internal.h"
30 #include "decode.h"
31 
32 #define NGLYPHS 256
33 #define GLYPH_COORD_VECT_SIZE 16
34 #define PALETTE_SIZE 256
35 #define PALETTE_DELTA 768
36 
37 static const int8_t glyph4_x[GLYPH_COORD_VECT_SIZE] = {
38  0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0, 1, 2, 2, 1
39 };
40 
41 static const int8_t glyph4_y[GLYPH_COORD_VECT_SIZE] = {
42  0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 2, 1, 1, 1, 2, 2
43 };
44 
45 static const int8_t glyph8_x[GLYPH_COORD_VECT_SIZE] = {
46  0, 2, 5, 7, 7, 7, 7, 7, 7, 5, 2, 0, 0, 0, 0, 0
47 };
48 
49 static const int8_t glyph8_y[GLYPH_COORD_VECT_SIZE] = {
50  0, 0, 0, 0, 1, 3, 4, 6, 7, 7, 7, 7, 6, 4, 3, 1
51 };
52 
53 /* codec47/bl16 motion vectors */
54 static const int8_t c47_mv[256][2] = {
55  { 0, 0 }, { -1, -43 }, { 6, -43 }, { -9, -42 }, { 13, -41 },
56  { -16, -40 }, { 19, -39 }, { -23, -36 }, { 26, -34 }, { -2, -33 },
57  { 4, -33 }, { -29, -32 }, { -9, -32 }, { 11, -31 }, { -16, -29 },
58  { 32, -29 }, { 18, -28 }, { -34, -26 }, { -22, -25 }, { -1, -25 },
59  { 3, -25 }, { -7, -24 }, { 8, -24 }, { 24, -23 }, { 36, -23 },
60  { -12, -22 }, { 13, -21 }, { -38, -20 }, { 0, -20 }, { -27, -19 },
61  { -4, -19 }, { 4, -19 }, { -17, -18 }, { -8, -17 }, { 8, -17 },
62  { 18, -17 }, { 28, -17 }, { 39, -17 }, { -12, -15 }, { 12, -15 },
63  { -21, -14 }, { -1, -14 }, { 1, -14 }, { -41, -13 }, { -5, -13 },
64  { 5, -13 }, { 21, -13 }, { -31, -12 }, { -15, -11 }, { -8, -11 },
65  { 8, -11 }, { 15, -11 }, { -2, -10 }, { 1, -10 }, { 31, -10 },
66  { -23, -9 }, { -11, -9 }, { -5, -9 }, { 4, -9 }, { 11, -9 },
67  { 42, -9 }, { 6, -8 }, { 24, -8 }, { -18, -7 }, { -7, -7 },
68  { -3, -7 }, { -1, -7 }, { 2, -7 }, { 18, -7 }, { -43, -6 },
69  { -13, -6 }, { -4, -6 }, { 4, -6 }, { 8, -6 }, { -33, -5 },
70  { -9, -5 }, { -2, -5 }, { 0, -5 }, { 2, -5 }, { 5, -5 },
71  { 13, -5 }, { -25, -4 }, { -6, -4 }, { -3, -4 }, { 3, -4 },
72  { 9, -4 }, { -19, -3 }, { -7, -3 }, { -4, -3 }, { -2, -3 },
73  { -1, -3 }, { 0, -3 }, { 1, -3 }, { 2, -3 }, { 4, -3 },
74  { 6, -3 }, { 33, -3 }, { -14, -2 }, { -10, -2 }, { -5, -2 },
75  { -3, -2 }, { -2, -2 }, { -1, -2 }, { 0, -2 }, { 1, -2 },
76  { 2, -2 }, { 3, -2 }, { 5, -2 }, { 7, -2 }, { 14, -2 },
77  { 19, -2 }, { 25, -2 }, { 43, -2 }, { -7, -1 }, { -3, -1 },
78  { -2, -1 }, { -1, -1 }, { 0, -1 }, { 1, -1 }, { 2, -1 },
79  { 3, -1 }, { 10, -1 }, { -5, 0 }, { -3, 0 }, { -2, 0 },
80  { -1, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 }, { 5, 0 },
81  { 7, 0 }, { -10, 1 }, { -7, 1 }, { -3, 1 }, { -2, 1 },
82  { -1, 1 }, { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 },
83  { -43, 2 }, { -25, 2 }, { -19, 2 }, { -14, 2 }, { -5, 2 },
84  { -3, 2 }, { -2, 2 }, { -1, 2 }, { 0, 2 }, { 1, 2 },
85  { 2, 2 }, { 3, 2 }, { 5, 2 }, { 7, 2 }, { 10, 2 },
86  { 14, 2 }, { -33, 3 }, { -6, 3 }, { -4, 3 }, { -2, 3 },
87  { -1, 3 }, { 0, 3 }, { 1, 3 }, { 2, 3 }, { 4, 3 },
88  { 19, 3 }, { -9, 4 }, { -3, 4 }, { 3, 4 }, { 7, 4 },
89  { 25, 4 }, { -13, 5 }, { -5, 5 }, { -2, 5 }, { 0, 5 },
90  { 2, 5 }, { 5, 5 }, { 9, 5 }, { 33, 5 }, { -8, 6 },
91  { -4, 6 }, { 4, 6 }, { 13, 6 }, { 43, 6 }, { -18, 7 },
92  { -2, 7 }, { 0, 7 }, { 2, 7 }, { 7, 7 }, { 18, 7 },
93  { -24, 8 }, { -6, 8 }, { -42, 9 }, { -11, 9 }, { -4, 9 },
94  { 5, 9 }, { 11, 9 }, { 23, 9 }, { -31, 10 }, { -1, 10 },
95  { 2, 10 }, { -15, 11 }, { -8, 11 }, { 8, 11 }, { 15, 11 },
96  { 31, 12 }, { -21, 13 }, { -5, 13 }, { 5, 13 }, { 41, 13 },
97  { -1, 14 }, { 1, 14 }, { 21, 14 }, { -12, 15 }, { 12, 15 },
98  { -39, 17 }, { -28, 17 }, { -18, 17 }, { -8, 17 }, { 8, 17 },
99  { 17, 18 }, { -4, 19 }, { 0, 19 }, { 4, 19 }, { 27, 19 },
100  { 38, 20 }, { -13, 21 }, { 12, 22 }, { -36, 23 }, { -24, 23 },
101  { -8, 24 }, { 7, 24 }, { -3, 25 }, { 1, 25 }, { 22, 25 },
102  { 34, 26 }, { -18, 28 }, { -32, 29 }, { 16, 29 }, { -11, 31 },
103  { 9, 32 }, { 29, 32 }, { -4, 33 }, { 2, 33 }, { -26, 34 },
104  { 23, 36 }, { -19, 39 }, { 16, 40 }, { -13, 41 }, { 9, 42 },
105  { -6, 43 }, { 1, 43 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
106 };
107 
108 /* codec37/48 motion vector tables: 3x 510 bytes/255 x-y pairs */
109 static const int8_t c37_mv[] = {
110  0, 0, 1, 0, 2, 0, 3, 0, 5, 0,
111  8, 0, 13, 0, 21, 0, -1, 0, -2, 0,
112  -3, 0, -5, 0, -8, 0, -13, 0, -17, 0,
113  -21, 0, 0, 1, 1, 1, 2, 1, 3, 1,
114  5, 1, 8, 1, 13, 1, 21, 1, -1, 1,
115  -2, 1, -3, 1, -5, 1, -8, 1, -13, 1,
116  -17, 1, -21, 1, 0, 2, 1, 2, 2, 2,
117  3, 2, 5, 2, 8, 2, 13, 2, 21, 2,
118  -1, 2, -2, 2, -3, 2, -5, 2, -8, 2,
119  -13, 2, -17, 2, -21, 2, 0, 3, 1, 3,
120  2, 3, 3, 3, 5, 3, 8, 3, 13, 3,
121  21, 3, -1, 3, -2, 3, -3, 3, -5, 3,
122  -8, 3, -13, 3, -17, 3, -21, 3, 0, 5,
123  1, 5, 2, 5, 3, 5, 5, 5, 8, 5,
124  13, 5, 21, 5, -1, 5, -2, 5, -3, 5,
125  -5, 5, -8, 5, -13, 5, -17, 5, -21, 5,
126  0, 8, 1, 8, 2, 8, 3, 8, 5, 8,
127  8, 8, 13, 8, 21, 8, -1, 8, -2, 8,
128  -3, 8, -5, 8, -8, 8, -13, 8, -17, 8,
129  -21, 8, 0, 13, 1, 13, 2, 13, 3, 13,
130  5, 13, 8, 13, 13, 13, 21, 13, -1, 13,
131  -2, 13, -3, 13, -5, 13, -8, 13, -13, 13,
132  -17, 13, -21, 13, 0, 21, 1, 21, 2, 21,
133  3, 21, 5, 21, 8, 21, 13, 21, 21, 21,
134  -1, 21, -2, 21, -3, 21, -5, 21, -8, 21,
135  -13, 21, -17, 21, -21, 21, 0, -1, 1, -1,
136  2, -1, 3, -1, 5, -1, 8, -1, 13, -1,
137  21, -1, -1, -1, -2, -1, -3, -1, -5, -1,
138  -8, -1, -13, -1, -17, -1, -21, -1, 0, -2,
139  1, -2, 2, -2, 3, -2, 5, -2, 8, -2,
140  13, -2, 21, -2, -1, -2, -2, -2, -3, -2,
141  -5, -2, -8, -2, -13, -2, -17, -2, -21, -2,
142  0, -3, 1, -3, 2, -3, 3, -3, 5, -3,
143  8, -3, 13, -3, 21, -3, -1, -3, -2, -3,
144  -3, -3, -5, -3, -8, -3, -13, -3, -17, -3,
145  -21, -3, 0, -5, 1, -5, 2, -5, 3, -5,
146  5, -5, 8, -5, 13, -5, 21, -5, -1, -5,
147  -2, -5, -3, -5, -5, -5, -8, -5, -13, -5,
148  -17, -5, -21, -5, 0, -8, 1, -8, 2, -8,
149  3, -8, 5, -8, 8, -8, 13, -8, 21, -8,
150  -1, -8, -2, -8, -3, -8, -5, -8, -8, -8,
151  -13, -8, -17, -8, -21, -8, 0, -13, 1, -13,
152  2, -13, 3, -13, 5, -13, 8, -13, 13, -13,
153  21, -13, -1, -13, -2, -13, -3, -13, -5, -13,
154  -8, -13, -13, -13, -17, -13, -21, -13, 0, -17,
155  1, -17, 2, -17, 3, -17, 5, -17, 8, -17,
156  13, -17, 21, -17, -1, -17, -2, -17, -3, -17,
157  -5, -17, -8, -17, -13, -17, -17, -17, -21, -17,
158  0, -21, 1, -21, 2, -21, 3, -21, 5, -21,
159  8, -21, 13, -21, 21, -21, -1, -21, -2, -21,
160  -3, -21, -5, -21, -8, -21, -13, -21, -17, -21,
161  0, 0, -8, -29, 8, -29, -18, -25, 17, -25,
162  0, -23, -6, -22, 6, -22, -13, -19, 12, -19,
163  0, -18, 25, -18, -25, -17, -5, -17, 5, -17,
164  -10, -15, 10, -15, 0, -14, -4, -13, 4, -13,
165  19, -13, -19, -12, -8, -11, -2, -11, 0, -11,
166  2, -11, 8, -11, -15, -10, -4, -10, 4, -10,
167  15, -10, -6, -9, -1, -9, 1, -9, 6, -9,
168  -29, -8, -11, -8, -8, -8, -3, -8, 3, -8,
169  8, -8, 11, -8, 29, -8, -5, -7, -2, -7,
170  0, -7, 2, -7, 5, -7, -22, -6, -9, -6,
171  -6, -6, -3, -6, -1, -6, 1, -6, 3, -6,
172  6, -6, 9, -6, 22, -6, -17, -5, -7, -5,
173  -4, -5, -2, -5, 0, -5, 2, -5, 4, -5,
174  7, -5, 17, -5, -13, -4, -10, -4, -5, -4,
175  -3, -4, -1, -4, 0, -4, 1, -4, 3, -4,
176  5, -4, 10, -4, 13, -4, -8, -3, -6, -3,
177  -4, -3, -3, -3, -2, -3, -1, -3, 0, -3,
178  1, -3, 2, -3, 4, -3, 6, -3, 8, -3,
179  -11, -2, -7, -2, -5, -2, -3, -2, -2, -2,
180  -1, -2, 0, -2, 1, -2, 2, -2, 3, -2,
181  5, -2, 7, -2, 11, -2, -9, -1, -6, -1,
182  -4, -1, -3, -1, -2, -1, -1, -1, 0, -1,
183  1, -1, 2, -1, 3, -1, 4, -1, 6, -1,
184  9, -1, -31, 0, -23, 0, -18, 0, -14, 0,
185  -11, 0, -7, 0, -5, 0, -4, 0, -3, 0,
186  -2, 0, -1, 0, 0, -31, 1, 0, 2, 0,
187  3, 0, 4, 0, 5, 0, 7, 0, 11, 0,
188  14, 0, 18, 0, 23, 0, 31, 0, -9, 1,
189  -6, 1, -4, 1, -3, 1, -2, 1, -1, 1,
190  0, 1, 1, 1, 2, 1, 3, 1, 4, 1,
191  6, 1, 9, 1, -11, 2, -7, 2, -5, 2,
192  -3, 2, -2, 2, -1, 2, 0, 2, 1, 2,
193  2, 2, 3, 2, 5, 2, 7, 2, 11, 2,
194  -8, 3, -6, 3, -4, 3, -2, 3, -1, 3,
195  0, 3, 1, 3, 2, 3, 3, 3, 4, 3,
196  6, 3, 8, 3, -13, 4, -10, 4, -5, 4,
197  -3, 4, -1, 4, 0, 4, 1, 4, 3, 4,
198  5, 4, 10, 4, 13, 4, -17, 5, -7, 5,
199  -4, 5, -2, 5, 0, 5, 2, 5, 4, 5,
200  7, 5, 17, 5, -22, 6, -9, 6, -6, 6,
201  -3, 6, -1, 6, 1, 6, 3, 6, 6, 6,
202  9, 6, 22, 6, -5, 7, -2, 7, 0, 7,
203  2, 7, 5, 7, -29, 8, -11, 8, -8, 8,
204  -3, 8, 3, 8, 8, 8, 11, 8, 29, 8,
205  -6, 9, -1, 9, 1, 9, 6, 9, -15, 10,
206  -4, 10, 4, 10, 15, 10, -8, 11, -2, 11,
207  0, 11, 2, 11, 8, 11, 19, 12, -19, 13,
208  -4, 13, 4, 13, 0, 14, -10, 15, 10, 15,
209  -5, 17, 5, 17, 25, 17, -25, 18, 0, 18,
210  -12, 19, 13, 19, -6, 22, 6, 22, 0, 23,
211  -17, 25, 18, 25, -8, 29, 8, 29, 0, 31,
212  0, 0, -6, -22, 6, -22, -13, -19, 12, -19,
213  0, -18, -5, -17, 5, -17, -10, -15, 10, -15,
214  0, -14, -4, -13, 4, -13, 19, -13, -19, -12,
215  -8, -11, -2, -11, 0, -11, 2, -11, 8, -11,
216  -15, -10, -4, -10, 4, -10, 15, -10, -6, -9,
217  -1, -9, 1, -9, 6, -9, -11, -8, -8, -8,
218  -3, -8, 0, -8, 3, -8, 8, -8, 11, -8,
219  -5, -7, -2, -7, 0, -7, 2, -7, 5, -7,
220  -22, -6, -9, -6, -6, -6, -3, -6, -1, -6,
221  1, -6, 3, -6, 6, -6, 9, -6, 22, -6,
222  -17, -5, -7, -5, -4, -5, -2, -5, -1, -5,
223  0, -5, 1, -5, 2, -5, 4, -5, 7, -5,
224  17, -5, -13, -4, -10, -4, -5, -4, -3, -4,
225  -2, -4, -1, -4, 0, -4, 1, -4, 2, -4,
226  3, -4, 5, -4, 10, -4, 13, -4, -8, -3,
227  -6, -3, -4, -3, -3, -3, -2, -3, -1, -3,
228  0, -3, 1, -3, 2, -3, 3, -3, 4, -3,
229  6, -3, 8, -3, -11, -2, -7, -2, -5, -2,
230  -4, -2, -3, -2, -2, -2, -1, -2, 0, -2,
231  1, -2, 2, -2, 3, -2, 4, -2, 5, -2,
232  7, -2, 11, -2, -9, -1, -6, -1, -5, -1,
233  -4, -1, -3, -1, -2, -1, -1, -1, 0, -1,
234  1, -1, 2, -1, 3, -1, 4, -1, 5, -1,
235  6, -1, 9, -1, -23, 0, -18, 0, -14, 0,
236  -11, 0, -7, 0, -5, 0, -4, 0, -3, 0,
237  -2, 0, -1, 0, 0, -23, 1, 0, 2, 0,
238  3, 0, 4, 0, 5, 0, 7, 0, 11, 0,
239  14, 0, 18, 0, 23, 0, -9, 1, -6, 1,
240  -5, 1, -4, 1, -3, 1, -2, 1, -1, 1,
241  0, 1, 1, 1, 2, 1, 3, 1, 4, 1,
242  5, 1, 6, 1, 9, 1, -11, 2, -7, 2,
243  -5, 2, -4, 2, -3, 2, -2, 2, -1, 2,
244  0, 2, 1, 2, 2, 2, 3, 2, 4, 2,
245  5, 2, 7, 2, 11, 2, -8, 3, -6, 3,
246  -4, 3, -3, 3, -2, 3, -1, 3, 0, 3,
247  1, 3, 2, 3, 3, 3, 4, 3, 6, 3,
248  8, 3, -13, 4, -10, 4, -5, 4, -3, 4,
249  -2, 4, -1, 4, 0, 4, 1, 4, 2, 4,
250  3, 4, 5, 4, 10, 4, 13, 4, -17, 5,
251  -7, 5, -4, 5, -2, 5, -1, 5, 0, 5,
252  1, 5, 2, 5, 4, 5, 7, 5, 17, 5,
253  -22, 6, -9, 6, -6, 6, -3, 6, -1, 6,
254  1, 6, 3, 6, 6, 6, 9, 6, 22, 6,
255  -5, 7, -2, 7, 0, 7, 2, 7, 5, 7,
256  -11, 8, -8, 8, -3, 8, 0, 8, 3, 8,
257  8, 8, 11, 8, -6, 9, -1, 9, 1, 9,
258  6, 9, -15, 10, -4, 10, 4, 10, 15, 10,
259  -8, 11, -2, 11, 0, 11, 2, 11, 8, 11,
260  19, 12, -19, 13, -4, 13, 4, 13, 0, 14,
261  -10, 15, 10, 15, -5, 17, 5, 17, 0, 18,
262  -12, 19, 13, 19, -6, 22, 6, 22, 0, 23,
263 };
264 
265 typedef struct SANMVideoContext {
268 
270  uint32_t pal[PALETTE_SIZE];
272 
273  ptrdiff_t pitch;
274  int width, height;
276  int prev_seq;
277 
279  uint16_t *fbuf, *frm0, *frm1, *frm2;
280  uint8_t *stored_frame;
282  uint32_t stor_size;
284 
285  uint8_t *rle_buf;
286  unsigned int rle_buf_size;
287 
289 
290  uint16_t codebook[256];
291  uint16_t small_codebook[4];
292 
293  int8_t p4x4glyphs[NGLYPHS][16];
294  int8_t p8x8glyphs[NGLYPHS][64];
295  uint8_t c47itbl[0x10000];
296  uint8_t c23lut[256];
297  uint8_t c4tbl[2][256][16];
298  uint16_t c4param;
299  uint8_t c47cb[4];
301 
302 enum GlyphEdge {
308 };
309 
310 enum GlyphDir {
316 };
317 
318 /**
319  * Return enum GlyphEdge of box where point (x, y) lies.
320  *
321  * @param x x point coordinate
322  * @param y y point coordinate
323  * @param edge_size box width/height.
324  */
325 static enum GlyphEdge which_edge(int x, int y, int edge_size)
326 {
327  const int edge_max = edge_size - 1;
328 
329  if (!y)
330  return BOTTOM_EDGE;
331  else if (y == edge_max)
332  return TOP_EDGE;
333  else if (!x)
334  return LEFT_EDGE;
335  else if (x == edge_max)
336  return RIGHT_EDGE;
337  else
338  return NO_EDGE;
339 }
340 
341 static enum GlyphDir which_direction(enum GlyphEdge edge0, enum GlyphEdge edge1)
342 {
343  if ((edge0 == LEFT_EDGE && edge1 == RIGHT_EDGE) ||
344  (edge1 == LEFT_EDGE && edge0 == RIGHT_EDGE) ||
345  (edge0 == BOTTOM_EDGE && edge1 != TOP_EDGE) ||
346  (edge1 == BOTTOM_EDGE && edge0 != TOP_EDGE))
347  return DIR_UP;
348  else if ((edge0 == TOP_EDGE && edge1 != BOTTOM_EDGE) ||
349  (edge1 == TOP_EDGE && edge0 != BOTTOM_EDGE))
350  return DIR_DOWN;
351  else if ((edge0 == LEFT_EDGE && edge1 != RIGHT_EDGE) ||
352  (edge1 == LEFT_EDGE && edge0 != RIGHT_EDGE))
353  return DIR_LEFT;
354  else if ((edge0 == TOP_EDGE && edge1 == BOTTOM_EDGE) ||
355  (edge1 == TOP_EDGE && edge0 == BOTTOM_EDGE) ||
356  (edge0 == RIGHT_EDGE && edge1 != LEFT_EDGE) ||
357  (edge1 == RIGHT_EDGE && edge0 != LEFT_EDGE))
358  return DIR_RIGHT;
359 
360  return NO_DIR;
361 }
362 
363 /* Interpolate two points. */
364 static void interp_point(int8_t *points, int x0, int y0, int x1, int y1,
365  int pos, int npoints)
366 {
367  if (npoints) {
368  points[0] = (x0 * pos + x1 * (npoints - pos) + (npoints >> 1)) / npoints;
369  points[1] = (y0 * pos + y1 * (npoints - pos) + (npoints >> 1)) / npoints;
370  } else {
371  points[0] = x0;
372  points[1] = y0;
373  }
374 }
375 
376 /**
377  * Construct glyphs by iterating through vector coordinates.
378  *
379  * @param pglyphs pointer to table where glyphs are stored
380  * @param xvec pointer to x component of vector coordinates
381  * @param yvec pointer to y component of vector coordinates
382  * @param side_length glyph width/height.
383  */
384 static void make_glyphs(int8_t *pglyphs, const int8_t *xvec, const int8_t *yvec,
385  const int side_length)
386 {
387  const int glyph_size = side_length * side_length;
388  int8_t *pglyph = pglyphs;
389 
390  int i, j;
391  for (i = 0; i < GLYPH_COORD_VECT_SIZE; i++) {
392  int x0 = xvec[i];
393  int y0 = yvec[i];
394  enum GlyphEdge edge0 = which_edge(x0, y0, side_length);
395 
396  for (j = 0; j < GLYPH_COORD_VECT_SIZE; j++, pglyph += glyph_size) {
397  int x1 = xvec[j];
398  int y1 = yvec[j];
399  enum GlyphEdge edge1 = which_edge(x1, y1, side_length);
400  enum GlyphDir dir = which_direction(edge0, edge1);
401  int npoints = FFMAX(FFABS(x1 - x0), FFABS(y1 - y0));
402  int ipoint;
403 
404  for (ipoint = 0; ipoint <= npoints; ipoint++) {
405  int8_t point[2];
406  int irow, icol;
407 
408  interp_point(point, x0, y0, x1, y1, ipoint, npoints);
409 
410  switch (dir) {
411  case DIR_UP:
412  for (irow = point[1]; irow >= 0; irow--)
413  pglyph[point[0] + irow * side_length] = 1;
414  break;
415 
416  case DIR_DOWN:
417  for (irow = point[1]; irow < side_length; irow++)
418  pglyph[point[0] + irow * side_length] = 1;
419  break;
420 
421  case DIR_LEFT:
422  for (icol = point[0]; icol >= 0; icol--)
423  pglyph[icol + point[1] * side_length] = 1;
424  break;
425 
426  case DIR_RIGHT:
427  for (icol = point[0]; icol < side_length; icol++)
428  pglyph[icol + point[1] * side_length] = 1;
429  break;
430  }
431  }
432  }
433  }
434 }
435 
436 static void init_sizes(SANMVideoContext *ctx, int width, int height)
437 {
438  ctx->width = width;
439  ctx->height = height;
440  ctx->npixels = width * height;
441 
442  ctx->aligned_width = FFALIGN(width, 8);
443  ctx->aligned_height = FFALIGN(height, 8);
444 
445  ctx->buf_size = ctx->aligned_width * ctx->aligned_height * sizeof(ctx->frm0[0]);
446  ctx->pitch = width;
447 }
448 
450 {
451  av_freep(&ctx->fbuf);
452  av_freep(&ctx->frm0);
453  av_freep(&ctx->frm1);
454  av_freep(&ctx->frm2);
455  av_freep(&ctx->stored_frame);
456  av_freep(&ctx->rle_buf);
457  ctx->frm0_size =
458  ctx->frm1_size =
459  ctx->frm2_size = 0;
460  init_sizes(ctx, 0, 0);
461 }
462 
464 {
465  av_fast_padded_mallocz(&ctx->fbuf, &ctx->fbuf_size, ctx->buf_size);
466  av_fast_padded_mallocz(&ctx->frm0, &ctx->frm0_size, ctx->buf_size);
467  av_fast_padded_mallocz(&ctx->frm1, &ctx->frm1_size, ctx->buf_size);
468  av_fast_padded_mallocz(&ctx->frm2, &ctx->frm2_size, ctx->buf_size);
469  if (!ctx->version) {
470  av_fast_padded_mallocz(&ctx->stored_frame,
471  &ctx->stored_frame_size, ctx->buf_size);
472  ctx->stor_size = 0;
473  }
474 
475  if (!ctx->frm0 || !ctx->frm1 || !ctx->frm2 ||
476  (!ctx->stored_frame && !ctx->version)) {
478  return AVERROR(ENOMEM);
479  }
480 
481  return 0;
482 }
483 
484 static void codec33_gen_tiles(SANMVideoContext *ctx, int8_t param1)
485 {
486  uint8_t *dst = &(ctx->c4tbl[0][0][0]);
487  int i, j, k, l, m, n, o, p;
488 
489  for (i = 0; i < 8; i++) {
490  for (k = 0; k < 8; k++) {
491  j = i + param1;
492  l = k + param1;
493  p = (j + l) >> 1;
494  n = (j + p) >> 1;
495  m = (p + l) >> 1;
496 
497  *dst++ = p; *dst++ = p; *dst++ = n; *dst++ = j;
498  *dst++ = p; *dst++ = p; *dst++ = n; *dst++ = j;
499  *dst++ = m; *dst++ = m; *dst++ = p; *dst++ = j;
500  *dst++ = l; *dst++ = l; *dst++ = m; *dst++ = p;
501  }
502  }
503 
504  for (i = 0; i < 8; i++) {
505  for (k = 0; k < 8; k++) {
506  j = i + param1;
507  l = k + param1;
508  n = (j + l) >> 1;
509  m = (l + n) >> 1;
510 
511  *dst++ = j; *dst++ = j; *dst++ = j; *dst++ = j;
512  *dst++ = n; *dst++ = n; *dst++ = n; *dst++ = n;
513  *dst++ = m; *dst++ = m; *dst++ = m; *dst++ = m;
514  *dst++ = l; *dst++ = l; *dst++ = l; *dst++ = l;
515  }
516  }
517 
518  for (i = 0; i < 8; i++) {
519  for (k = 0; k < 8; k++) {
520  j = i + param1;
521  l = k + param1;
522  m = (j + l) >> 1;
523  n = (j + m) >> 1;
524  o = (l + m) >> 1;
525 
526  *dst++ = j; *dst++ = j; *dst++ = n; *dst++ = m;
527  *dst++ = j; *dst++ = j; *dst++ = n; *dst++ = m;
528  *dst++ = n; *dst++ = n; *dst++ = m; *dst++ = o;
529  *dst++ = m; *dst++ = m; *dst++ = o; *dst++ = l;
530  }
531  }
532 
533  for (i = 0; i < 8; i++) {
534  for (k = 0; k < 8; k++) {
535  j = i + param1;
536  l = k + param1;
537  m = (j + l) >> 1;
538  n = (l + m) >> 1;
539 
540  *dst++ = j; *dst++ = m; *dst++ = n; *dst++ = l;
541  *dst++ = j; *dst++ = m; *dst++ = n; *dst++ = l;
542  *dst++ = j; *dst++ = m; *dst++ = n; *dst++ = l;
543  *dst++ = j; *dst++ = m; *dst++ = n; *dst++ = l;
544  }
545  }
546 }
547 
548 static void codec4_gen_tiles(SANMVideoContext *ctx, uint16_t param1)
549 {
550  uint8_t *dst = &(ctx->c4tbl[0][0][0]);
551  int i, j, k, l, m, n, o;
552 
553  for (i = 1; i < 16; i += 2) {
554  for (k = 0; k < 16; k++) {
555  j = i + param1;
556  l = k + param1;
557  m = (j + l) / 2;
558  n = (j + m) / 2;
559  o = (l + m) / 2;
560  if (j == m || l == m) {
561  *dst++ = l; *dst++ = j; *dst++ = l; *dst++ = j;
562  *dst++ = j; *dst++ = l; *dst++ = j; *dst++ = j;
563  *dst++ = l; *dst++ = j; *dst++ = l; *dst++ = j;
564  *dst++ = l; *dst++ = l; *dst++ = j; *dst++ = l;
565  } else {
566  *dst++ = m; *dst++ = m; *dst++ = n; *dst++ = j;
567  *dst++ = m; *dst++ = m; *dst++ = n; *dst++ = j;
568  *dst++ = o; *dst++ = o; *dst++ = m; *dst++ = n;
569  *dst++ = l; *dst++ = l; *dst++ = o; *dst++ = m;
570  }
571  }
572  }
573 
574  for (i = 0; i < 16; i += 2) {
575  for (k = 0; k < 16; k++) {
576  j = i + param1;
577  l = k + param1;
578  m = (j + l) / 2;
579  n = (j + m) / 2;
580  o = (l + m) / 2;
581  if (m == j || m == l) {
582  *dst++ = j; *dst++ = j; *dst++ = l; *dst++ = j;
583  *dst++ = j; *dst++ = j; *dst++ = j; *dst++ = l;
584  *dst++ = l; *dst++ = j; *dst++ = l; *dst++ = l;
585  *dst++ = j; *dst++ = l; *dst++ = j; *dst++ = l;
586  } else {
587  *dst++ = j; *dst++ = j; *dst++ = n; *dst++ = m;
588  *dst++ = j; *dst++ = j; *dst++ = n; *dst++ = m;
589  *dst++ = n; *dst++ = n; *dst++ = m; *dst++ = o;
590  *dst++ = m; *dst++ = m; *dst++ = o; *dst++ = l;
591  }
592  }
593  }
594 }
595 
596 
598  uint16_t param2, uint8_t clr)
599 {
600  uint8_t c, *dst = (uint8_t *)&(ctx->c4tbl[1][0][0]);
601  uint32_t loop = param2 * 8;
602 
603  if ((param2 > 256) || (bytestream2_get_bytes_left(gb) < loop))
604  return AVERROR_INVALIDDATA;
605 
606  while (loop--) {
607  c = bytestream2_get_byteu(gb);
608  *dst++ = (c >> 4) + clr;
609  *dst++ = (c & 0xf) + clr;
610  }
611 
612  return 0;
613 }
614 
615 static void rotate_bufs(SANMVideoContext *ctx, int rotate_code)
616 {
617  if (rotate_code == 2)
618  FFSWAP(uint16_t*, ctx->frm1, ctx->frm2);
619  FFSWAP(uint16_t*, ctx->frm2, ctx->frm0);
620 }
621 
623 {
624  SANMVideoContext *ctx = avctx->priv_data;
625 
626  ctx->avctx = avctx;
627  ctx->version = !avctx->extradata_size;
628  // early sanity check before allocations to avoid need for deallocation code.
629  if (!ctx->version && avctx->extradata_size < 1026) {
630  av_log(avctx, AV_LOG_ERROR, "Not enough extradata.\n");
631  return AVERROR_INVALIDDATA;
632  }
633 
634  avctx->pix_fmt = ctx->version ? AV_PIX_FMT_RGB565 : AV_PIX_FMT_PAL8;
635 
636  if (!ctx->version) {
637  // ANIM has no dimensions in the header, distrust the incoming data.
638  avctx->width = avctx->height = 0;
639  ctx->have_dimensions = 0;
640  } else if (avctx->width > 800 || avctx->height > 600 ||
641  avctx->width < 8 || avctx->height < 8) {
642  // BL16 valid range is 8x8 - 800x600
643  return AVERROR_INVALIDDATA;
644  }
645  init_sizes(ctx, avctx->width, avctx->height);
646  if (init_buffers(ctx)) {
647  av_log(avctx, AV_LOG_ERROR, "Error allocating buffers.\n");
648  return AVERROR(ENOMEM);
649  }
650 
651  make_glyphs(ctx->p4x4glyphs[0], glyph4_x, glyph4_y, 4);
652  make_glyphs(ctx->p8x8glyphs[0], glyph8_x, glyph8_y, 8);
653 
654  if (!ctx->version) {
655  int i;
656 
657  ctx->subversion = AV_RL16(avctx->extradata);
658  for (i = 0; i < PALETTE_SIZE; i++)
659  ctx->pal[i] = 0xFFU << 24 | AV_RL32(avctx->extradata + 2 + i * 4);
660  if (ctx->subversion < 2)
661  ctx->pal[0] = 0xFFU << 24;
662  }
663  ctx->c4param = 0xffff;
664 
665  return 0;
666 }
667 
669 {
670  SANMVideoContext *ctx = avctx->priv_data;
671 
673 
674  return 0;
675 }
676 
677 static int old_codec4(SANMVideoContext *ctx, GetByteContext *gb, int top, int left,
678  int w, int h, uint8_t param, uint16_t param2, int codec)
679 {
680  const uint16_t mx = ctx->width, my = ctx->height, p = ctx->pitch;
681  uint8_t mask, bits, idx, *gs, *dst = (uint8_t *)ctx->fbuf;
682  int i, j, k, l, bit, ret, x, y;
683 
684  if (ctx->c4param != param) {
685  if (codec > 32)
686  codec33_gen_tiles(ctx, param);
687  else
688  codec4_gen_tiles(ctx, param);
689  ctx->c4param = param;
690  }
691  if (param2 > 0) {
692  ret = codec4_load_tiles(ctx, gb, param2, param);
693  if (ret)
694  return ret;
695  }
696 
697  if (codec > 32)
698  codec -= 29;
699 
700  for (j = 0; j < w; j += 4) {
701  mask = bits = 0;
702  x = left + j;
703  for (i = 0; i < h; i += 4) {
704  y = top + i;
705  if (param2 > 0) {
706  if (bits == 0) {
707  if (bytestream2_get_bytes_left(gb) < 1)
708  return AVERROR_INVALIDDATA;
709  mask = bytestream2_get_byteu(gb);
710  bits = 8;
711  }
712  bit = !!(mask & 0x80);
713  mask <<= 1;
714  bits--;
715  } else {
716  bit = 0;
717  }
718 
719  if (bytestream2_get_bytes_left(gb) < 1)
720  return AVERROR_INVALIDDATA;
721  idx = bytestream2_get_byteu(gb);
722  if ((bit == 0) && (idx == 0x80) && (codec != 5))
723  continue;
724  if ((y >= my) || ((y + 4) < 0) || ((x + 4) < 0) || (x >= mx))
725  continue;
726  gs = &(ctx->c4tbl[bit][idx][0]);
727  if ((y >= 0) && (x >= 0) && ((y + 4) < my) && ((x + 4) < mx)) {
728  for (k = 0; k < 4; k++, gs += 4)
729  memcpy(dst + x + (y + k) * p, gs, 4);
730  } else {
731  for (k = 0; k < 4; k++) {
732  for (l = 0; l < 4; l++, gs++) {
733  const int yo = y + k, xo = x + l;
734  if ((yo >= 0) && (yo < my) && (xo >= 0) && (xo < mx))
735  *(dst + yo * p + xo) = *gs;
736  }
737  }
738  }
739  }
740  }
741  return 0;
742 }
743 
744 static int rle_decode(SANMVideoContext *ctx, GetByteContext *gb, uint8_t *dst, const int out_size)
745 {
746  int opcode, color, run_len, left = out_size;
747 
748  while (left > 0) {
749  opcode = bytestream2_get_byte(gb);
750  run_len = (opcode >> 1) + 1;
751  if (run_len > left || bytestream2_get_bytes_left(gb) <= 0)
752  return AVERROR_INVALIDDATA;
753 
754  if (opcode & 1) {
755  color = bytestream2_get_byte(gb);
756  memset(dst, color, run_len);
757  } else {
759  return AVERROR_INVALIDDATA;
761  }
762 
763  dst += run_len;
764  left -= run_len;
765  }
766 
767  return 0;
768 }
769 
770 static int old_codec23(SANMVideoContext *ctx, GetByteContext *gb, int top, int left,
771  int width, int height, uint8_t param, uint16_t param2)
772 {
773  const uint16_t mx = ctx->width, my = ctx->height, p = ctx->pitch;
774  uint8_t c, lut[256], *dst = (uint8_t *)ctx->fbuf;
775  int sk, i, j, ls, pc, y;
776 
777  if (ctx->subversion < 2) {
778  /* Rebel Assault 1: constant offset + 0xd0 */
779  for (i = 0; i < 256; i++)
780  lut[i] = (i + param + 0xd0) & 0xff;
781  } else if (param2 == 256) {
782  if (bytestream2_get_bytes_left(gb) < 256)
783  return AVERROR_INVALIDDATA;
784  bytestream2_get_bufferu(gb, ctx->c23lut, 256);
785  } else if (param2 < 256) {
786  for (i = 0; i < 256; i++)
787  lut[i] = (i + param2) & 0xff;
788  } else {
789  memcpy(lut, ctx->c23lut, 256);
790  }
791  if (bytestream2_get_bytes_left(gb) < 1)
792  return 0; /* some c23 frames just set up the LUT */
793 
794  if (((top + height) < 0) || (top >= my) || (left + width < 0) || (left >= mx))
795  return 0;
796 
797  if (top < 0) {
798  y = -top;
799  while (y-- && bytestream2_get_bytes_left(gb) > 1) {
800  ls = bytestream2_get_le16u(gb);
801  if (bytestream2_get_bytes_left(gb) < ls)
802  return AVERROR_INVALIDDATA;
803  bytestream2_skip(gb, ls);
804  }
805  height += top;
806  top = 0;
807  }
808 
809  y = top;
810  for (; (bytestream2_get_bytes_left(gb) > 1) && (height > 0) && (y < my); height--, y++) {
811  ls = bytestream2_get_le16u(gb);
812  sk = 1;
813  pc = left;
814  while ((bytestream2_get_bytes_left(gb) > 0) && (ls > 0) && (pc <= (width + left))) {
815  j = bytestream2_get_byteu(gb);
816  ls--;
817  if (!sk) {
818  while (j--) {
819  if ((pc >= 0) && (pc < mx)) {
820  c = *(dst + (y * p) + pc);
821  *(dst + (y * p) + pc) = lut[c];
822  }
823  if (pc < mx)
824  pc++;
825  }
826  } else {
827  if (pc < mx)
828  pc += j;
829  }
830  sk ^= 1;
831  }
832  }
833  return 0;
834 }
835 
836 static int old_codec21(SANMVideoContext *ctx, GetByteContext *gb, int top, int left,
837  int width, int height)
838 {
839  const uint16_t mx = ctx->width, my = ctx->height, p = ctx->pitch;
840  uint8_t *dst = (uint8_t *)ctx->fbuf, c;
841  int j, y, pc, sk, ls;
842 
843  if (((top + height) < 0) || (top >= my) || (left + width < 0) || (left >= mx))
844  return 0;
845 
846  y = top;
847  for (; (bytestream2_get_bytes_left(gb) > 2) && (height > 0) && (y < my); height--, y++) {
848  ls = bytestream2_get_le16u(gb);
849  if (y < 0) {
850  if (ls >= bytestream2_get_bytes_left(gb))
851  return 0;
852  bytestream2_skip(gb, ls);
853  continue;
854  }
855  sk = 1;
856  pc = left;
857  while ((bytestream2_get_bytes_left(gb) > 1) && (ls > 1) && (pc <= (width + left))) {
858  j = bytestream2_get_le16u(gb);
859  ls -= 2;
860  if (sk) {
861  if (pc < mx)
862  pc += j;
863  } else {
864  while ((bytestream2_get_bytes_left(gb) > 0) && (ls > 0) && (j >= 0)) {
865  c = bytestream2_get_byteu(gb);
866  if ((pc >= 0) && (pc < mx)) {
867  *(dst + (y * p) + pc) = c;
868  }
869  ls--;
870  j--;
871  if (pc < mx)
872  pc++;
873  }
874  }
875  sk ^= 1;
876  }
877  }
878  return 0;
879 }
880 
881 static int old_codec1(SANMVideoContext *ctx, GetByteContext *gb, int top,
882  int left, int width, int height, int opaque)
883 {
884  const uint16_t mx = ctx->width, my = ctx->height, p = ctx->pitch;
885  uint8_t *dst = (uint8_t *)ctx->fbuf, code, c;
886  int j, x, y, flag, dlen;
887 
888  if (((top + height) < 0) || (top >= my) || (left + width < 0) || (left >= mx))
889  return 0;
890 
891  if (top < 0) {
892  y = -top;
893  while (y-- && bytestream2_get_bytes_left(gb) > 1) {
894  dlen = bytestream2_get_le16u(gb);
895  if (bytestream2_get_bytes_left(gb) <= dlen)
896  return AVERROR_INVALIDDATA;
897  bytestream2_skip(gb, dlen);
898  }
899  height += top;
900  top = 0;
901  }
902 
903  y = top;
904  for (; (bytestream2_get_bytes_left(gb) > 1) && (height > 0) && (y < my); height--, y++) {
905  dlen = bytestream2_get_le16u(gb);
906  x = left;
907  while (bytestream2_get_bytes_left(gb) > 1 && dlen) {
908  code = bytestream2_get_byteu(gb);
909  dlen--;
910  flag = code & 1;
911  code = (code >> 1) + 1;
912  if (flag) {
913  c = bytestream2_get_byteu(gb);
914  dlen--;
915  if (x >= mx)
916  continue;
917  if (x < 0) {
918  int dff = FFMIN(-x, code);
919  code -= dff;
920  x += dff;
921  }
922  if (x + code >= mx)
923  code = mx - x;
924  if (code < 1)
925  continue;
926  for (j = 0; (j < code) && (c || opaque); j++) {
927  *(dst + (y * p) + x + j) = c;
928  }
929  x += code;
930  } else {
932  return AVERROR_INVALIDDATA;
933  for (j = 0; j < code; j++) {
934  c = bytestream2_get_byteu(gb);
935  if ((x >= 0) && (x < mx) && (c || opaque))
936  *(dst + (y * p) + x) = c;
937  if (x < mx)
938  x++;
939  }
940  dlen -= code;
941  }
942  }
943  }
944 
945  return 0;
946 }
947 
948 static int old_codec31(SANMVideoContext *ctx, GetByteContext *gb, int top,
949  int left, int width, int height, int p1, int opaque)
950 {
951  const uint16_t mx = ctx->width, my = ctx->height, p = ctx->pitch;
952  uint8_t *dst = (uint8_t *)ctx->fbuf, c;
953  int j, x, y, flag, dlen, code;
954 
955  if (((top + height) < 0) || (top >= my) || (left + width < 0) || (left >= mx))
956  return 0;
957 
958  if (top < 0) {
959  y = -top;
960  while (y-- && bytestream2_get_bytes_left(gb) > 1) {
961  dlen = bytestream2_get_le16u(gb);
962  if (bytestream2_get_bytes_left(gb) <= dlen)
963  return AVERROR_INVALIDDATA;
964  bytestream2_skip(gb, dlen);
965  }
966  height += top;
967  top = 0;
968  }
969 
970  y = top;
971  for (; (bytestream2_get_bytes_left(gb) > 1) && (height > 0) && (y < my); height--, y++) {
972  dlen = bytestream2_get_le16u(gb);
973  x = left;
974  while (bytestream2_get_bytes_left(gb) > 1 && dlen) {
975  code = bytestream2_get_byteu(gb);
976  dlen--;
977  flag = code & 1;
978  code = (code >> 1) + 1;
979  if (flag) {
980  c = bytestream2_get_byteu(gb);
981  dlen--;
982  for (j = 0; (j < code); j++) {
983  if ((opaque || (c & 0xf)) && (x >= 0) && (x < mx))
984  *(dst + (y * p) + x) = p1 + (c & 0xf);
985  if (x < mx)
986  x++;
987  if ((opaque || (c >> 4)) && (x >= 0) && (x < mx))
988  *(dst + (y * p) + x) = p1 + (c >> 4);
989  if (x < mx)
990  x++;
991  }
992  } else {
994  return AVERROR_INVALIDDATA;
995  for (j = 0; j < code; j++) {
996  c = bytestream2_get_byteu(gb);
997  if ((opaque || (c & 0xf)) && (x >= 0) && (x < mx))
998  *(dst + (y * p) + x) = p1 + (c & 0xf);
999  if (x < mx)
1000  x++;
1001  if ((opaque || (c >> 4)) && (x >= 0) && (x < mx))
1002  *(dst + (y * p) + x) = p1 + (c >> 4);
1003  if (x < mx)
1004  x++;
1005  }
1006  dlen -= code;
1007  }
1008  }
1009  }
1010 
1011  return 0;
1012 }
1013 
1014 static int old_codec2(SANMVideoContext *ctx, GetByteContext *gb, int top,
1015  int left, int width, int height)
1016 {
1017  uint8_t *dst = (uint8_t *)ctx->fbuf, col;
1018  int16_t xpos = left, ypos = top;
1019 
1020  while (bytestream2_get_bytes_left(gb) > 3) {
1021  xpos += bytestream2_get_le16u(gb);
1022  ypos += bytestream2_get_byteu(gb);
1023  col = bytestream2_get_byteu(gb);
1024  if (xpos >= 0 && ypos >= 0 &&
1025  xpos < ctx->width && ypos < ctx->height) {
1026  *(dst + xpos + ypos * ctx->pitch) = col;
1027  }
1028  }
1029  return 0;
1030 }
1031 
1032 static void blt_solid(uint8_t *dst, const uint8_t *src, int16_t left, int16_t top,
1033  uint16_t srcxoff, uint16_t srcyoff, uint16_t srcwidth,
1034  uint16_t srcheight, const uint16_t srcpitch, const uint16_t dstpitch,
1035  const uint16_t dstheight, int32_t size)
1036 {
1037  if ((srcwidth < 1) || (srcheight < 1) || (size < 1))
1038  return;
1039 
1040  if (top < 0) {
1041  if (-top >= srcheight)
1042  return;
1043  srcyoff -= top;
1044  srcheight += top;
1045  size += (srcpitch * top);
1046  top = 0;
1047  }
1048 
1049  if ((top + srcheight) > dstheight) {
1050  int clip = (top + srcheight) - dstheight;
1051  if (clip >= srcheight)
1052  return;
1053  srcheight -= clip;
1054  }
1055 
1056  if (left < 0) {
1057  if (-left >= srcwidth)
1058  return;
1059  srcxoff -= left;
1060  srcwidth += left;
1061  size += left;
1062  left = 0;
1063  }
1064 
1065  if (left + srcwidth > dstpitch) {
1066  int clip = (left + srcwidth) - dstpitch;
1067  if (clip >= srcwidth)
1068  return;
1069  srcwidth -= clip;
1070  }
1071 
1072  src += ((uintptr_t)srcyoff * srcpitch) + srcxoff;
1073  dst += ((uintptr_t)top * dstpitch) + left;
1074  while ((srcheight--) && (size >= srcwidth)) {
1075  memcpy(dst, src, srcwidth);
1076  src += srcpitch;
1077  dst += dstpitch;
1078  size -= srcpitch;
1079  }
1080  if ((size > 0) && (size < srcwidth) && (srcheight > 0))
1081  memcpy(dst, src, size);
1082 }
1083 
1084 static void blt_mask(uint8_t *dst, const uint8_t *src, int16_t left, int16_t top,
1085  uint16_t srcxoff, uint16_t srcyoff, uint16_t srcwidth,
1086  uint16_t srcheight, const uint16_t srcpitch, const uint16_t dstpitch,
1087  const uint16_t dstheight, int32_t size, const uint8_t skipcolor)
1088 {
1089  if ((srcwidth < 1) || (srcheight < 1) || (size < 1))
1090  return;
1091 
1092  if (top < 0) {
1093  if (-top >= srcheight)
1094  return;
1095  srcyoff -= top;
1096  srcheight += top;
1097  size += (srcpitch * top);
1098  top = 0;
1099  }
1100 
1101  if ((top + srcheight) > dstheight) {
1102  int clip = (top + srcheight) - dstheight;
1103  if (clip >= srcheight)
1104  return;
1105  srcheight -= clip;
1106  }
1107 
1108  if (left < 0) {
1109  if (-left >= srcwidth)
1110  return;
1111  srcxoff -= left;
1112  srcwidth += left;
1113  size += left;
1114  left = 0;
1115  }
1116 
1117  if (left + srcwidth > dstpitch) {
1118  int clip = (left + srcwidth) - dstpitch;
1119  if (clip >= srcwidth)
1120  return;
1121  srcwidth -= clip;
1122  }
1123 
1124  src += ((uintptr_t)srcyoff * srcpitch) + srcxoff;
1125  dst += ((uintptr_t)top * dstpitch) + left;
1126  for (int i = 0; (size > 0) && (i < srcheight); i++) {
1127  for (int j = 0; (size > 0) && (j < srcwidth); j++, size--) {
1128  if (src[j] != skipcolor)
1129  dst[j] = src[j];
1130  }
1131  src += srcpitch;
1132  dst += dstpitch;
1133  }
1134 }
1135 
1136 static void blt_ipol(uint8_t *dst, const uint8_t *src1, const uint8_t *src2,
1137  int16_t left, int16_t top, uint16_t srcxoff, uint16_t srcyoff,
1138  uint16_t srcwidth, uint16_t srcheight, const uint16_t srcpitch,
1139  const uint16_t dstpitch, const uint16_t dstheight, int32_t size,
1140  const uint8_t *itbl)
1141 {
1142  if ((srcwidth < 1) || (srcheight < 1) || (size < 1))
1143  return;
1144 
1145  if (top < 0) {
1146  if (-top >= srcheight)
1147  return;
1148  srcyoff -= top;
1149  srcheight += top;
1150  size += (srcpitch * top);
1151  top = 0;
1152  }
1153 
1154  if ((top + srcheight) > dstheight) {
1155  int clip = (top + srcheight) - dstheight;
1156  if (clip >= srcheight)
1157  return;
1158  srcheight -= clip;
1159  }
1160 
1161  if (left < 0) {
1162  if (-left >= srcwidth)
1163  return;
1164  srcxoff -= left;
1165  srcwidth += left;
1166  size += left;
1167  left = 0;
1168  }
1169 
1170  if (left + srcwidth > dstpitch) {
1171  int clip = (left + srcwidth) - dstpitch;
1172  if (clip >= srcwidth)
1173  return;
1174  srcwidth -= clip;
1175  }
1176 
1177  src1 += ((uintptr_t)srcyoff * srcpitch) + srcxoff;
1178  src2 += ((uintptr_t)srcyoff * srcpitch) + srcxoff;
1179  dst += ((uintptr_t)top * dstpitch) + left;
1180  for (int i = 0; (size > 0) && (i < srcheight); i++) {
1181  for (int j = 0; (size > 0) && (j < srcwidth); j++, size--) {
1182  dst[j] = itbl[(src1[j] << 8) | src2[j]];
1183  }
1184  src1 += srcpitch;
1185  src2 += srcpitch;
1186  dst += dstpitch;
1187  }
1188 }
1189 
1190 static int old_codec20(SANMVideoContext *ctx, GetByteContext *gb, int top, int left,
1191  const int w, const int h)
1192 {
1193  blt_solid((uint8_t*)ctx->fbuf, gb->buffer, left, top, 0, 0, w, h, w, ctx->pitch,
1194  ctx->height, FFMIN(bytestream2_get_bytes_left(gb), w * h));
1195 
1196  return 0;
1197 }
1198 
1199 static inline void codec37_mv(uint8_t *dst, const uint8_t *src,
1200  int height, int stride, int x, int y)
1201 {
1202  int pos, i, j;
1203 
1204  pos = x + y * stride;
1205  for (j = 0; j < 4; j++) {
1206  for (i = 0; i < 4; i++) {
1207  if ((pos + i) < 0 || (pos + i) >= height * stride)
1208  dst[i] = 0;
1209  else
1210  dst[i] = src[i];
1211  }
1212  dst += stride;
1213  src += stride;
1214  pos += stride;
1215  }
1216 }
1217 
1218 static int old_codec37(SANMVideoContext *ctx, GetByteContext *gb, int top, int left,
1219  int width, int height)
1220 {
1221  int i, j, k, l, t, run, len, code, skip, mx, my;
1222  uint8_t *dst, *prev;
1223  int skip_run = 0;
1224 
1225  width = FFALIGN(width, 4);
1226  if (width > ctx->aligned_width)
1227  return AVERROR_INVALIDDATA;
1228 
1229  if (bytestream2_get_bytes_left(gb) < 16)
1230  return AVERROR_INVALIDDATA;
1231 
1232  int compr = bytestream2_get_byteu(gb);
1233  int mvoff = bytestream2_get_byteu(gb);
1234  int seq = bytestream2_get_le16u(gb);
1235  uint32_t decoded_size = bytestream2_get_le32u(gb);
1236  int flags;
1237 
1238  bytestream2_skip(gb, 4);
1239  flags = bytestream2_get_byteu(gb);
1240  bytestream2_skip(gb, 3);
1241 
1242  if (decoded_size > height * width) {
1243  decoded_size = height * width;
1244  av_log(ctx->avctx, AV_LOG_WARNING, "Decoded size is too large.\n");
1245  }
1246 
1247  if (((seq & 1) || !(flags & 1)) && (compr && compr != 2)) {
1248  FFSWAP(uint16_t*, ctx->frm0, ctx->frm2);
1249  }
1250 
1251  dst = ((uint8_t*)ctx->frm0);
1252  prev = ((uint8_t*)ctx->frm2);
1253 
1254  if (mvoff > 2) {
1255  av_log(ctx->avctx, AV_LOG_ERROR, "Invalid motion base value %d.\n", mvoff);
1256  return AVERROR_INVALIDDATA;
1257  }
1258 
1259  switch (compr) {
1260  case 0:
1262  return AVERROR_INVALIDDATA;
1264  memset(ctx->frm2, 0, ctx->frm2_size);
1265  break;
1266  case 1:
1267  run = 0;
1268  len = -1;
1269  code = 0;
1270 
1271  for (j = 0; j < height; j += 4) {
1272  for (i = 0; i < width; i += 4) {
1273  if (len < 0) {
1274  if (bytestream2_get_bytes_left(gb) < 1)
1275  return AVERROR_INVALIDDATA;
1276  code = bytestream2_get_byte(gb);
1277  len = code >> 1;
1278  run = code & 1;
1279  skip = 0;
1280  } else {
1281  skip = run;
1282  }
1283 
1284  if (!skip) {
1285  if (bytestream2_get_bytes_left(gb) < 1)
1286  return AVERROR_INVALIDDATA;
1287  code = bytestream2_get_byte(gb);
1288  if (code == 0xff) {
1289  len--;
1290  for (k = 0; k < 4; k++) {
1291  for (l = 0; l < 4; l++) {
1292  if (len < 0) {
1293  if (bytestream2_get_bytes_left(gb) < 1)
1294  return AVERROR_INVALIDDATA;
1295  code = bytestream2_get_byte(gb);
1296  len = code >> 1;
1297  run = code & 1;
1298  if (run) {
1299  if (bytestream2_get_bytes_left(gb) < 1)
1300  return AVERROR_INVALIDDATA;
1301  code = bytestream2_get_byte(gb);
1302  }
1303  }
1304  if (!run) {
1305  if (bytestream2_get_bytes_left(gb) < 1)
1306  return AVERROR_INVALIDDATA;
1307  code = bytestream2_get_byte(gb);
1308  }
1309  *(dst + i + (k * width) + l) = code;
1310  len--;
1311  }
1312  }
1313  continue;
1314  }
1315  }
1316  /* 4x4 block copy from prev with MV */
1317  code = (code == 0xff) ? 0 : code;
1318  mx = c37_mv[(mvoff * 255 + code) * 2];
1319  my = c37_mv[(mvoff * 255 + code) * 2 + 1];
1320  codec37_mv(dst + i, prev + i + mx + my * width,
1321  height, width, i + mx, j + my);
1322  len--;
1323  }
1324  dst += width * 4;
1325  prev += width * 4;
1326  }
1327  break;
1328  case 2:
1329  if (rle_decode(ctx, gb, dst, decoded_size))
1330  return AVERROR_INVALIDDATA;
1331  memset(ctx->frm2, 0, ctx->frm2_size);
1332  break;
1333  case 3:
1334  case 4:
1335  for (j = 0; j < height; j += 4) {
1336  for (i = 0; i < width; i += 4) {
1337  int code;
1338  if (skip_run) {
1339  skip_run--;
1340  copy_block4(dst + i, prev + i, width, width, 4);
1341  continue;
1342  }
1343  if (bytestream2_get_bytes_left(gb) < 1)
1344  return AVERROR_INVALIDDATA;
1345  code = bytestream2_get_byteu(gb);
1346  if (code == 0xFF) {
1347  if (bytestream2_get_bytes_left(gb) < 16)
1348  return AVERROR_INVALIDDATA;
1349  for (k = 0; k < 4; k++)
1350  bytestream2_get_bufferu(gb, dst + i + k * width, 4);
1351  } else if ((flags & 4) && (code == 0xFE)) {
1352  if (bytestream2_get_bytes_left(gb) < 4)
1353  return AVERROR_INVALIDDATA;
1354  for (k = 0; k < 4; k += 2) {
1355  uint8_t c1 = bytestream2_get_byteu(gb);
1356  uint8_t c2 = bytestream2_get_byteu(gb);
1357  for (l = 0; l < 2; l++) {
1358  *(dst + i + ((k + l) * width) + 0) = c1;
1359  *(dst + i + ((k + l) * width) + 1) = c1;
1360  *(dst + i + ((k + l) * width) + 2) = c2;
1361  *(dst + i + ((k + l) * width) + 3) = c2;
1362  }
1363  }
1364  } else if ((flags & 4) && (code == 0xFD)) {
1365  if (bytestream2_get_bytes_left(gb) < 1)
1366  return AVERROR_INVALIDDATA;
1367  t = bytestream2_get_byteu(gb);
1368  for (k = 0; k < 4; k++)
1369  memset(dst + i + k * width, t, 4);
1370  } else {
1371  mx = c37_mv[(mvoff * 255 + code) * 2];
1372  my = c37_mv[(mvoff * 255 + code) * 2 + 1];
1373  codec37_mv(dst + i, prev + i + mx + my * width,
1374  height, width, i + mx, j + my);
1375 
1376  if ((compr == 4) && (code == 0)) {
1377  if (bytestream2_get_bytes_left(gb) < 1)
1378  return AVERROR_INVALIDDATA;
1379  skip_run = bytestream2_get_byteu(gb);
1380  }
1381  }
1382  }
1383  dst += width * 4;
1384  prev += width * 4;
1385  }
1386  break;
1387  default:
1389  "Subcodec 37 compression %d", compr);
1390  return AVERROR_PATCHWELCOME;
1391  }
1392 
1393  if ((flags & 2) == 0) {
1394  blt_solid((uint8_t*)ctx->fbuf, (uint8_t*)ctx->frm0, left, top, 0, 0, width,
1395  height, width, ctx->pitch, ctx->height, width * height);
1396  } else {
1397  blt_mask((uint8_t*)ctx->fbuf, (uint8_t*)ctx->frm0, left, top, 0, 0, width,
1398  height, width, ctx->pitch, ctx->height, width * height, 0);
1399  }
1400  return 0;
1401 }
1402 
1404  uint8_t *prev1, uint8_t *prev2, int stride, int size)
1405 {
1406  int code, k, t;
1407  uint8_t colors[2];
1408  int8_t *pglyph;
1409 
1410  if (bytestream2_get_bytes_left(gb) < 1)
1411  return AVERROR_INVALIDDATA;
1412 
1413  code = bytestream2_get_byteu(gb);
1414  if (code >= 0xF8) {
1415  switch (code) {
1416  case 0xFF:
1417  if (size == 2) {
1418  if (bytestream2_get_bytes_left(gb) < 4)
1419  return AVERROR_INVALIDDATA;
1420  dst[0] = bytestream2_get_byteu(gb);
1421  dst[1] = bytestream2_get_byteu(gb);
1422  dst[0 + stride] = bytestream2_get_byteu(gb);
1423  dst[1 + stride] = bytestream2_get_byteu(gb);
1424  } else {
1425  size >>= 1;
1426  if (codec47_block(ctx, gb, dst, prev1, prev2, stride, size))
1427  return AVERROR_INVALIDDATA;
1428  if (codec47_block(ctx, gb, dst + size, prev1 + size, prev2 + size,
1429  stride, size))
1430  return AVERROR_INVALIDDATA;
1431  dst += size * stride;
1432  prev1 += size * stride;
1433  prev2 += size * stride;
1434  if (codec47_block(ctx, gb, dst, prev1, prev2, stride, size))
1435  return AVERROR_INVALIDDATA;
1436  if (codec47_block(ctx, gb, dst + size, prev1 + size, prev2 + size,
1437  stride, size))
1438  return AVERROR_INVALIDDATA;
1439  }
1440  break;
1441  case 0xFE:
1442  if (bytestream2_get_bytes_left(gb) < 1)
1443  return AVERROR_INVALIDDATA;
1444 
1445  t = bytestream2_get_byteu(gb);
1446  for (k = 0; k < size; k++)
1447  memset(dst + k * stride, t, size);
1448  break;
1449  case 0xFD:
1450  if (bytestream2_get_bytes_left(gb) < 3)
1451  return AVERROR_INVALIDDATA;
1452 
1453  code = bytestream2_get_byteu(gb);
1454  pglyph = (size == 8) ? ctx->p8x8glyphs[code] : ctx->p4x4glyphs[code];
1455  bytestream2_get_bufferu(gb, colors, 2);
1456 
1457  for (k = 0; k < size; k++)
1458  for (t = 0; t < size; t++)
1459  dst[t + k * stride] = colors[!*pglyph++];
1460  break;
1461  case 0xFC:
1462  for (k = 0; k < size; k++)
1463  memcpy(dst + k * stride, prev1 + k * stride, size);
1464  break;
1465  default:
1466  for (k = 0; k < size; k++)
1467  memset(dst + k * stride, ctx->c47cb[code & 3], size);
1468  }
1469  } else {
1470  int mx = c47_mv[code][0];
1471  int my = c47_mv[code][1];
1472  int index = prev2 - (const uint8_t *)ctx->frm2;
1473 
1474  av_assert2(index >= 0 && index < (ctx->buf_size >> 1));
1475 
1476  if (index < -mx - my * stride ||
1477  (ctx->buf_size >> 1) - index < mx + size + (my + size - 1) * stride) {
1478  av_log(ctx->avctx, AV_LOG_ERROR, "MV is invalid.\n");
1479  return AVERROR_INVALIDDATA;
1480  }
1481 
1482  for (k = 0; k < size; k++)
1483  memcpy(dst + k * stride, prev2 + mx + (my + k) * stride, size);
1484  }
1485 
1486  return 0;
1487 }
1488 
1489 static void codec47_read_interptable(GetByteContext *gb, uint8_t *itbl)
1490 {
1491  uint8_t *p1, *p2;
1492  int i, j;
1493 
1494  for (i = 0; i < 256; i++) {
1495  p1 = p2 = itbl + i;
1496  for (j = 256 - i; j; j--) {
1497  *p1 = *p2 = bytestream2_get_byte(gb);
1498  p1 += 1;
1499  p2 += 256;
1500  }
1501  itbl += 256;
1502  }
1503 }
1504 
1505 static void codec47_comp1(GetByteContext *gb, uint8_t *dst_in, int width,
1506  const int height, const ptrdiff_t stride, const uint8_t *itbl)
1507 {
1508  uint8_t p1, *dst;
1509  uint16_t px;
1510  int i, j;
1511 
1512  dst = dst_in + stride;
1513  for (i = 0; i < height; i += 2) {
1514  p1 = bytestream2_get_byte(gb);
1515  *dst++ = p1;
1516  *dst++ = p1;
1517  px = p1;
1518  for (j = 2; j < width; j += 2) {
1519  p1 = bytestream2_get_byte(gb);
1520  px = (px << 8) | p1;
1521  *dst++ = itbl[px];
1522  *dst++ = p1;
1523  }
1524  dst += stride;
1525  }
1526 
1527  memcpy(dst_in, dst_in + stride, width);
1528  dst = dst_in + stride + stride;
1529  for (i = 2; i < height - 1; i += 2) {
1530  for (j = 0; j < width; j++) {
1531  px = (*(dst - stride) << 8) | *(dst + stride);
1532  *dst++ = itbl[px];
1533  }
1534  dst += stride;
1535  }
1536 }
1537 
1538 static int old_codec47(SANMVideoContext *ctx, GetByteContext *gb, int top, int left,
1539  int width, int height)
1540 {
1541  uint32_t decoded_size;
1542  int i, j;
1543  uint8_t *dst = (uint8_t *)ctx->frm0;
1544  uint8_t *prev1 = (uint8_t *)ctx->frm1;
1545  uint8_t *prev2 = (uint8_t *)ctx->frm2;
1546  uint8_t auxcol[2];
1547 
1548  width = FFALIGN(width, 8);
1549  if (width > ctx->aligned_width)
1550  return AVERROR_INVALIDDATA;
1551 
1552  if (bytestream2_get_bytes_left(gb) < 26)
1553  return AVERROR_INVALIDDATA;
1554 
1555  int seq = bytestream2_get_le16u(gb);
1556  int compr = bytestream2_get_byteu(gb);
1557  int new_rot = bytestream2_get_byteu(gb);
1558  int skip = bytestream2_get_byteu(gb);
1559 
1560  bytestream2_skip(gb, 3);
1561  bytestream2_get_bufferu(gb, ctx->c47cb, 4);
1562  auxcol[0] = bytestream2_get_byteu(gb);
1563  auxcol[1] = bytestream2_get_byteu(gb);
1564  decoded_size = bytestream2_get_le32u(gb);
1565  bytestream2_skip(gb, 8);
1566 
1567  if (decoded_size > ctx->aligned_height * width) {
1568  decoded_size = height * width;
1569  av_log(ctx->avctx, AV_LOG_WARNING, "Decoded size is too large.\n");
1570  }
1571 
1572  if (skip & 1) {
1573  if (bytestream2_get_bytes_left(gb) < 0x8080)
1574  return AVERROR_INVALIDDATA;
1575  codec47_read_interptable(gb, ctx->c47itbl);
1576  }
1577  if (!seq) {
1578  ctx->prev_seq = -1;
1579  memset(prev1, auxcol[0], ctx->frm0_size);
1580  memset(prev2, auxcol[1], ctx->frm0_size);
1581  }
1582 
1583  switch (compr) {
1584  case 0:
1586  return AVERROR_INVALIDDATA;
1588  break;
1589  case 1:
1590  if (bytestream2_get_bytes_left(gb) < ((width + 1) >> 1) * ((height + 1) >> 1))
1591  return AVERROR_INVALIDDATA;
1592  codec47_comp1(gb, dst, width, height, width, ctx->c47itbl);
1593  break;
1594  case 2:
1595  if (seq == ctx->prev_seq + 1) {
1596  for (j = 0; j < height; j += 8) {
1597  for (i = 0; i < width; i += 8)
1598  if (codec47_block(ctx, gb, dst + i, prev1 + i, prev2 + i, width, 8))
1599  return AVERROR_INVALIDDATA;
1600  dst += width * 8;
1601  prev1 += width * 8;
1602  prev2 += width * 8;
1603  }
1604  }
1605  break;
1606  case 3:
1607  memcpy(ctx->frm0, ctx->frm2, ctx->frm0_size);
1608  break;
1609  case 4:
1610  memcpy(ctx->frm0, ctx->frm1, ctx->frm0_size);
1611  break;
1612  case 5:
1613  if (rle_decode(ctx, gb, dst, decoded_size))
1614  return AVERROR_INVALIDDATA;
1615  break;
1616  default:
1618  "Subcodec 47 compression %d", compr);
1619  return AVERROR_PATCHWELCOME;
1620  }
1621 
1622  blt_solid((uint8_t*)ctx->fbuf, (uint8_t*)ctx->frm0, left, top, 0, 0, width,
1623  height, width, ctx->pitch, ctx->height, width * height);
1624 
1625  if ((seq == ctx->prev_seq + 1) && new_rot)
1626  rotate_bufs(ctx, new_rot);
1627 
1628  ctx->prev_seq = seq;
1629 
1630  return 0;
1631 }
1632 
1633 // scale 4x4 input block to an 8x8 output block
1634 static void c48_4to8(uint8_t *dst, const uint8_t *src, const uint16_t w)
1635 {
1636  uint16_t p;
1637  // dst is always at least 16bit aligned
1638  for (int i = 0; i < 4; i++) {
1639  for (int j = 0; j < 8; j += 2) {
1640  p = *src++;
1641  p = (p << 8) | p;
1642  *((uint16_t *)(dst + w * 0 + j)) = p;
1643  *((uint16_t *)(dst + w * 1 + j)) = p;
1644  }
1645  dst += w * 2;
1646  }
1647 }
1648 
1649 static int c48_invalid_mv(int x, int y, const uint16_t w, int h, int blocksize, int mvofs) {
1650  if (mvofs < -x + -y*w)
1651  return AVERROR_INVALIDDATA;
1652 
1653  if (mvofs > w-x-blocksize + w*(h-y-blocksize))
1654  return AVERROR_INVALIDDATA;
1655 
1656  return 0;
1657 }
1658 
1659 static int codec48_block(GetByteContext *gb, uint8_t *dst, uint8_t *db, int x, int y,
1660  const uint16_t w, const int aligned_height, const uint8_t *itbl)
1661 {
1662  uint8_t opc, sb[16];
1663  int i, j, k, l;
1664  int16_t mvofs;
1665  uint32_t ofs;
1666 
1667  if (bytestream2_get_bytes_left(gb) < 1)
1668  return 1;
1669 
1670  opc = bytestream2_get_byteu(gb);
1671  switch (opc) {
1672  case 0xFF: // 1x1 -> 8x8 block scale
1673  if (bytestream2_get_bytes_left(gb) < 1)
1674  return 1;
1675 
1676  if (y > 0 && x > 0) {
1677  sb[15] = bytestream2_get_byteu(gb);
1678  sb[ 7] = itbl[(*(dst - 1*w + 7) << 8) | sb[15]];
1679  sb[ 3] = itbl[(*(dst - 1*w + 7) << 8) | sb[ 7]];
1680  sb[11] = itbl[(sb[15] << 8) | sb[ 7]];
1681  sb[ 1] = itbl[(*(dst + 0*w - 1) << 8) | sb[ 3]];
1682  sb[ 0] = itbl[(*(dst + 0*w - 1) << 8) | sb[ 1]];
1683  sb[ 2] = itbl[(sb[ 3] << 8) | sb[ 1]];
1684  sb[ 5] = itbl[(*(dst + 2*w - 1) << 8) | sb[ 7]];
1685  sb[ 4] = itbl[(*(dst + 2*w - 1) << 8) | sb[ 5]];
1686  sb[ 6] = itbl[(sb[ 7] << 8) | sb[ 5]];
1687  sb[ 9] = itbl[(*(dst + 3*w - 1) << 8) | sb[11]];
1688  sb[ 8] = itbl[(*(dst + 3*w - 1) << 8) | sb[ 9]];
1689  sb[10] = itbl[(sb[11] << 8) | sb[ 9]];
1690  sb[13] = itbl[(*(dst + 4*w - 1) << 8) | sb[15]];
1691  sb[12] = itbl[(*(dst + 4*w - 1) << 8) | sb[13]];
1692  sb[14] = itbl[(sb[15] << 8) | sb[13]];
1693  } else {
1694  opc = bytestream2_get_byteu(gb);
1695  for (i = 0; i < 16; i++)
1696  sb[i] = opc;
1697  }
1698  c48_4to8(dst, sb, w);
1699  break;
1700  case 0xFE: // 1x 8x8 copy from deltabuf, 16bit mv from source
1701  if (bytestream2_get_bytes_left(gb) < 2)
1702  return 1;
1703  mvofs = bytestream2_get_le16(gb);
1704  if (c48_invalid_mv(x, y, w, aligned_height, 8, mvofs))
1705  break;
1706  for (i = 0; i < 8; i++) {
1707  ofs = w * i;
1708  for (k = 0; k < 8; k++)
1709  *(dst + ofs + k) = *(db + ofs + k + mvofs);
1710  }
1711  break;
1712  case 0xFD: // 2x2 -> 8x8 block scale
1713  if (bytestream2_get_bytes_left(gb) < 4)
1714  return 1;
1715  sb[ 5] = bytestream2_get_byteu(gb);
1716  sb[ 7] = bytestream2_get_byteu(gb);
1717  sb[13] = bytestream2_get_byteu(gb);
1718  sb[15] = bytestream2_get_byteu(gb);
1719 
1720  if (y > 0 && x >0) {
1721  sb[ 1] = itbl[(*(dst - 1*w + 3) << 8) | sb[ 5]];
1722  sb[ 3] = itbl[(*(dst - 1*w + 7) << 8) | sb[ 7]];
1723  sb[ 9] = itbl[(sb[13] << 8) | sb[ 5]];
1724  sb[11] = itbl[(sb[15] << 8) | sb[ 7]];
1725  sb[ 0] = itbl[(*(dst + 0*w - 1) << 8) | sb[ 1]];
1726  sb[ 2] = itbl[(sb[ 3] << 8) | sb[ 1]];
1727  sb[ 4] = itbl[(*(dst + 2*w - 1) << 8) | sb[ 5]];
1728  sb[ 6] = itbl[(sb[ 7] << 8) | sb[ 5]];
1729  sb[ 8] = itbl[(*(dst + 3*w - 1) << 8) | sb[ 9]];
1730  sb[10] = itbl[(sb[11] << 8) | sb[ 9]];
1731  sb[12] = itbl[(*(dst + 4*w - 1) << 8) | sb[13]];
1732  sb[14] = itbl[(sb[15] << 8) | sb[13]];
1733  } else {
1734  sb[ 0] = sb[ 1] = sb[ 4] = sb[ 5];
1735  sb[ 2] = sb[ 3] = sb[ 6] = sb[ 7];
1736  sb[ 8] = sb[ 9] = sb[12] = sb[13];
1737  sb[10] = sb[11] = sb[14] = sb[15];
1738  }
1739  c48_4to8(dst, sb, w);
1740  break;
1741  case 0xFC: // 4x copy 4x4 block, per-block c37_mv from source
1742  if (bytestream2_get_bytes_left(gb) < 4)
1743  return 1;
1744  for (i = 0; i < 8; i += 4) {
1745  for (k = 0; k < 8; k += 4) {
1746  opc = bytestream2_get_byteu(gb);
1747  opc = (opc == 255) ? 0 : opc;
1748  mvofs = c37_mv[opc * 2] + (c37_mv[opc * 2 + 1] * w);
1749  if (c48_invalid_mv(x+k, y+i, w, aligned_height, 4, mvofs))
1750  continue;
1751  for (j = 0; j < 4; j++) {
1752  ofs = (w * (j + i)) + k;
1753  for (l = 0; l < 4; l++)
1754  *(dst + ofs + l) = *(db + ofs + l + mvofs);
1755  }
1756  }
1757  }
1758  break;
1759  case 0xFB: // Copy 4x 4x4 blocks, per-block mv from source
1760  if (bytestream2_get_bytes_left(gb) < 8)
1761  return 1;
1762  for (i = 0; i < 8; i += 4) {
1763  for (k = 0; k < 8; k += 4) {
1764  mvofs = bytestream2_get_le16(gb);
1765  if (c48_invalid_mv(x+k, y+i, w, aligned_height, 4, mvofs))
1766  continue;
1767  for (j = 0; j < 4; j++) {
1768  ofs = (w * (j + i)) + k;
1769  for (l = 0; l < 4; l++)
1770  *(dst + ofs + l) = *(db + ofs + l + mvofs);
1771  }
1772  }
1773  }
1774  break;
1775  case 0xFA: // scale 4x4 input block to 8x8 dest block
1776  if (bytestream2_get_bytes_left(gb) < 16)
1777  return 1;
1778  bytestream2_get_bufferu(gb, sb, 16);
1779  c48_4to8(dst, sb, w);
1780  break;
1781  case 0xF9: // 16x 2x2 copy from delta, per-block c37_mv from source
1782  if (bytestream2_get_bytes_left(gb) < 16)
1783  return 1;
1784  for (i = 0; i < 8; i += 2) {
1785  for (j = 0; j < 8; j += 2) {
1786  ofs = (w * i) + j;
1787  opc = bytestream2_get_byteu(gb);
1788  opc = (opc == 255) ? 0 : opc;
1789  mvofs = c37_mv[opc * 2] + (c37_mv[opc * 2 + 1] * w);
1790  if (c48_invalid_mv(x+j, y+i, w, aligned_height, 2, mvofs))
1791  continue;
1792  for (l = 0; l < 2; l++) {
1793  *(dst + ofs + l + 0) = *(db + ofs + l + 0 + mvofs);
1794  *(dst + ofs + l + w) = *(db + ofs + l + w + mvofs);
1795  }
1796  }
1797  }
1798  break;
1799  case 0xF8: // 16x 2x2 blocks copy, 16bit mv from source
1800  if (bytestream2_get_bytes_left(gb) < 32)
1801  return 1;
1802  for (i = 0; i < 8; i += 2) {
1803  for (j = 0; j < 8; j += 2) {
1804  ofs = w * i + j;
1805  mvofs = bytestream2_get_le16(gb);
1806  if (c48_invalid_mv(x+j, y+i, w, aligned_height, 2, mvofs))
1807  continue;
1808  for (l = 0; l < 2; l++) {
1809  *(dst + ofs + l + 0) = *(db + ofs + l + 0 + mvofs);
1810  *(dst + ofs + l + w) = *(db + ofs + l + w + mvofs);
1811  }
1812  }
1813  }
1814  break;
1815  case 0xF7: // copy 8x8 block from src to dest
1816  if (bytestream2_get_bytes_left(gb) < 64)
1817  return 1;
1818  for (i = 0; i < 8; i++) {
1819  ofs = i * w;
1820  for (l = 0; l < 8; l++)
1821  *(dst + ofs + l) = bytestream2_get_byteu(gb);
1822  }
1823  break;
1824  default: // copy 8x8 block from prev, c37_mv from source
1825  mvofs = c37_mv[opc * 2] + (c37_mv[opc * 2 + 1] * w);
1826  if (c48_invalid_mv(x, y, w, aligned_height, 8, mvofs))
1827  break;
1828  for (i = 0; i < 8; i++) {
1829  ofs = i * w;
1830  for (l = 0; l < 8; l++)
1831  *(dst + ofs + l) = *(db + ofs + l + mvofs);
1832  }
1833  break;
1834  }
1835  return 0;
1836 }
1837 
1838 static int old_codec48(SANMVideoContext *ctx, GetByteContext *gb, int top, int left,
1839  int width, int height)
1840 {
1841  uint8_t *dst, *prev;
1842  int i, j, flags, ah;
1843 
1844  width = FFALIGN(width, 8);
1845  if (width > ctx->aligned_width)
1846  return AVERROR_INVALIDDATA;
1847 
1848  ah = FFALIGN(height, 8);
1849  if (ah > ctx->aligned_height)
1850  return AVERROR_INVALIDDATA;
1851 
1852  if (bytestream2_get_bytes_left(gb) < 16)
1853  return AVERROR_INVALIDDATA;
1854 
1855  int compr = bytestream2_get_byteu(gb);
1856  int mvidx = bytestream2_get_byteu(gb);
1857  int seq = bytestream2_get_le16u(gb);
1858  uint32_t decoded_size = bytestream2_get_le32u(gb);
1859 
1860  // all codec48 videos use 1, but just to be safe...
1861  if (mvidx != 1) {
1862  av_log(ctx->avctx, AV_LOG_ERROR, "Invalid motion base value %d.\n", mvidx);
1863  return AVERROR_INVALIDDATA;
1864  }
1865 
1866  bytestream2_skip(gb, 4);
1867  flags = bytestream2_get_byteu(gb);
1868  bytestream2_skip(gb, 3);
1869 
1870  if (flags & 8) {
1871  if (bytestream2_get_bytes_left(gb) < 0x8080)
1872  return AVERROR_INVALIDDATA;
1873  codec47_read_interptable(gb, ctx->c47itbl);
1874  }
1875 
1876  dst = (uint8_t*)ctx->frm0;
1877  prev = (uint8_t*)ctx->frm2;
1878 
1879  if (seq == 0)
1880  memset(ctx->frm2, 0, ctx->frm2_size);
1881 
1882  switch (compr) {
1883  case 0:
1885  return AVERROR_INVALIDDATA;
1887  break;
1888  case 2:
1889  if (decoded_size > width * height) {
1890  av_log(ctx->avctx, AV_LOG_ERROR, "Decoded size %u is too large.\n", decoded_size);
1891  decoded_size = width * height;
1892  }
1893 
1894  if (rle_decode(ctx, gb, dst, decoded_size))
1895  return AVERROR_INVALIDDATA;
1896  break;
1897  case 3:
1898  if ((seq == 0) || (seq == ctx->prev_seq + 1)) {
1899  if ((seq & 1) || ((flags & 1) == 0) || (flags & 0x10)) {
1900  FFSWAP(uint16_t*, ctx->frm0, ctx->frm2);
1901  dst = (uint8_t*)ctx->frm0;
1902  prev = (uint8_t*)ctx->frm2;
1903  }
1904  for (j = 0; j < height; j += 8) {
1905  for (i = 0; i < width; i += 8) {
1906  if (codec48_block(gb, dst + i, prev + i, i, j, width,
1907  ah, ctx->c47itbl))
1908  return AVERROR_INVALIDDATA;
1909  }
1910  dst += width * 8;
1911  prev += width * 8;
1912  }
1913  }
1914  break;
1915  case 5:
1916  if (bytestream2_get_bytes_left(gb) < ((width + 1) >> 1) * ((height + 1) >> 1))
1917  return AVERROR_INVALIDDATA;
1918  codec47_comp1(gb, dst, width, height, width, ctx->c47itbl);
1919  break;
1920  case 6: /* this is a "stub" frame that follows a frame with flag 0x10 set. */
1921  break;
1922  default:
1924  "Subcodec 48 compression %d", compr);
1925  return AVERROR_PATCHWELCOME;
1926  }
1927 
1928  ctx->prev_seq = seq;
1929  if ((flags & 2) == 0) {
1930  if (flags & 0x10) {
1931  /* generate an artificial frame from the 2 buffers. This will be
1932  * followed up immediately with a codec48 compression 6 frame, which
1933  * will then blit the actual decoding result (frm0) to the main buffer.
1934  */
1935  blt_ipol((uint8_t*)ctx->fbuf, (uint8_t*)ctx->frm0, (uint8_t*)ctx->frm2,
1936  left, top, 0, 0, width, height, width, ctx->pitch, ctx->height,
1937  width * height, ctx->c47itbl);
1938  return 0;
1939  }
1940  blt_solid((uint8_t*)ctx->fbuf, (uint8_t*)ctx->frm0, left, top, 0, 0, width,
1941  height, width, ctx->pitch, ctx->height, width * height);
1942  } else {
1943  blt_mask((uint8_t*)ctx->fbuf, (uint8_t*)ctx->frm0, left, top, 0, 0, width,
1944  height, width, ctx->pitch, ctx->height, width * height, 0);
1945  }
1946  return 0;
1947 }
1948 
1950  int xoff, int yoff)
1951 {
1952  uint16_t w, h, parm2;
1953  uint8_t codec, param;
1954  int16_t left, top;
1955  int fsc;
1956 
1957  codec = bytestream2_get_byteu(gb);
1958  param = bytestream2_get_byteu(gb);
1959  left = bytestream2_get_le16u(gb) + xoff;
1960  top = bytestream2_get_le16u(gb) + yoff;
1961  w = bytestream2_get_le16u(gb);
1962  h = bytestream2_get_le16u(gb);
1963  bytestream2_skip(gb, 2);
1964  parm2 = bytestream2_get_le16u(gb);
1965 
1966  if (w < 1 || h < 1 || w > 640 || h > 480 || left > 640 || top > 480 || left + w <= 0 || top + h <= 0) {
1967  av_log(ctx->avctx, AV_LOG_WARNING,
1968  "ignoring invalid fobj dimensions: c%d %d %d @ %d %d\n",
1969  codec, w, h, left, top);
1970  return 0;
1971  }
1972 
1973  /* codecs with their own buffers */
1974  fsc = (codec == 37 || codec == 47 || codec == 48);
1975 
1976  /* special case for "Shadows of the Empire" videos: they have top=60
1977  * at all frames to vertically center the video in the 640x480 game
1978  * window, but we don't need that.
1979  */
1980  if ((w == 640) && (h == 272) && (top == 60) && (codec == 47))
1981  left = top = 0;
1982 
1983  if (!ctx->have_dimensions) {
1984  int xres, yres;
1985  if (ctx->subversion < 2) {
1986  /* Rebel Assault 1: 384x242 internal size */
1987  xres = 384;
1988  yres = 242;
1989  if (w > xres || h > yres)
1990  return AVERROR_INVALIDDATA;
1991  ctx->have_dimensions = 1;
1992  } else if (fsc) {
1993  /* these codecs work on full frames, trust their dimensions */
1994  xres = w;
1995  yres = h;
1996  ctx->have_dimensions = 1;
1997  } else {
1998  /* detect common sizes */
1999  xres = w + left;
2000  yres = h + top;
2001  if (((xres == 424) && (yres == 260)) || /* RA2 */
2002  ((xres == 320) && (yres == 200)) || /* FT/Dig */
2003  ((xres == 640) && (yres == 272)) || /* SotE */
2004  ((xres == 640) && (yres == 350)) || /* MotS */
2005  ((xres == 640) && (yres == 480))) {
2006  ctx->have_dimensions = 1;
2007  }
2008 
2009  xres = FFMAX(xres, ctx->width);
2010  yres = FFMAX(yres, ctx->height);
2011  }
2012 
2013  if ((xres < (fsc ? 8 : 1)) || (yres < (fsc ? 8 : 1)) || (xres > 640) || (yres > 480))
2014  return AVERROR_INVALIDDATA;
2015 
2016  if (ctx->width < xres || ctx->height < yres) {
2017  int ret = ff_set_dimensions(ctx->avctx, xres, yres);
2018  if (ret < 0)
2019  return ret;
2020  init_sizes(ctx, xres, yres);
2021  if (init_buffers(ctx)) {
2022  av_log(ctx->avctx, AV_LOG_ERROR, "Error resizing buffers.\n");
2023  return AVERROR(ENOMEM);
2024  }
2025  }
2026  } else {
2027  if (((w > ctx->width) || (h > ctx->height) || (w * h > ctx->buf_size)) && fsc) {
2028  /* correct unexpected overly large frames: this happens
2029  * for instance with The Dig's sq1.san video: it has a few
2030  * (all black) 640x480 frames halfway in, while the rest is
2031  * 320x200.
2032  */
2033  av_log(ctx->avctx, AV_LOG_WARNING,
2034  "resizing too large fobj: c%d %d %d @ %d %d\n", codec, w, h, left, top);
2035  w = ctx->width;
2036  h = ctx->height;
2037  }
2038  }
2039 
2040  /* users of codecs>=37 are subversion 2, enforce that for STOR/FTCH */
2041  if (fsc && ctx->subversion < 2) {
2042  ctx->subversion = 2;
2043  ctx->stor_size = 0; /* invalidate existing data */
2044  }
2045 
2046  /* clear the main buffer on the first fob */
2047  if (ctx->first_fob) {
2048  ctx->first_fob = 0;
2049  if (!fsc)
2050  memset(ctx->fbuf, 0, ctx->frm0_size);
2051  }
2052 
2053  switch (codec) {
2054  case 1:
2055  case 3:
2056  return old_codec1(ctx, gb, top, left, w, h, codec == 3);
2057  case 2:
2058  return old_codec2(ctx, gb, top, left, w, h);
2059  case 4:
2060  case 5:
2061  case 33:
2062  case 34:
2063  return old_codec4(ctx, gb, top, left, w, h, param, parm2, codec);
2064  case 20:
2065  return old_codec20(ctx, gb, top, left, w, h);
2066  case 21:
2067  return old_codec21(ctx, gb, top, left, w, h);
2068  case 23:
2069  return old_codec23(ctx, gb, top, left, w, h, param, parm2);
2070  case 31:
2071  case 32:
2072  return old_codec31(ctx, gb, top, left, w, h, param, (codec == 32));
2073  case 37:
2074  return old_codec37(ctx, gb, top, left, w, h); break;
2075  case 45:
2076  return 0;
2077  case 47:
2078  return old_codec47(ctx, gb, top, left, w, h); break;
2079  case 48:
2080  return old_codec48(ctx, gb, top, left, w, h); break;
2081  default:
2082  avpriv_request_sample(ctx->avctx, "Subcodec %d", codec);
2083  ctx->frame->flags |= AV_FRAME_FLAG_CORRUPT;
2084  break;
2085  }
2086  return 0;
2087 }
2088 
2090 {
2091  int xoff, yoff, ret;
2092  GetByteContext gb;
2093 
2094  /* FTCH defines additional x/y offsets */
2095  if (size == 6) {
2096  bytestream2_skip(&ctx->gb, 2);
2097  xoff = bytestream2_get_le16u(&ctx->gb);
2098  yoff = bytestream2_get_le16u(&ctx->gb);
2099  } else if (size == 12) {
2101  bytestream2_skip(&ctx->gb, 4);
2102  xoff = bytestream2_get_be32u(&ctx->gb);
2103  yoff = bytestream2_get_be32u(&ctx->gb);
2104  } else
2105  return 1;
2106 
2107  if (ctx->stor_size > 0) {
2108  /* decode the stored FOBJ */
2109  uint8_t *bitstream = av_malloc(ctx->stor_size + AV_INPUT_BUFFER_PADDING_SIZE);
2110  if (!bitstream)
2111  return AVERROR(ENOMEM);
2112  memcpy(bitstream, ctx->stored_frame, ctx->stor_size);
2113  bytestream2_init(&gb, bitstream, ctx->stor_size);
2114  ret = process_frame_obj(ctx, &gb, xoff, yoff);
2115  av_free(bitstream);
2116  } else {
2117  /* this happens a lot in RA1: The individual files are meant to
2118  * be played in sequence, with some referencing objects STORed
2119  * by previous files, e.g. the cockpit codec21 object in RA1 LVL8.
2120  * But spamming the log with errors is also not helpful, so
2121  * here we simply ignore this case. Return 1 to indicate that
2122  * there was no valid image fetched.
2123  */
2124  ret = 1;
2125  }
2126  return ret;
2127 }
2128 
2130 {
2131  int16_t *dp = ctx->delta_pal;
2132  uint32_t *pal = ctx->pal;
2133  uint16_t cmd;
2134  uint8_t c[3];
2135  int i, j;
2136 
2137  if (size < 4)
2138  return AVERROR_INVALIDDATA;
2139  bytestream2_skip(&ctx->gb, 2);
2140  cmd = bytestream2_get_be16(&ctx->gb);
2141  size -= 4;
2142 
2143  if (cmd == 1) {
2144  for (i = 0; i < PALETTE_DELTA; i += 3) {
2145  for (j = 0; j < 3; j++) {
2146  ctx->shift_pal[i + j] += dp[i + j];
2147  c[j] = av_clip_uint8(ctx->shift_pal[i + j] >> 7) & 0xFFU;
2148  }
2149  *pal++ = 0xFFU << 24 | c[0] << 16 | c[1] << 8 | c[2];
2150  }
2151  } else if (cmd == 0 || cmd == 2) {
2152  if (size < PALETTE_DELTA * 2) {
2153  av_log(ctx->avctx, AV_LOG_ERROR,
2154  "Incorrect palette change block size %"PRIu32".\n", size);
2155  return AVERROR_INVALIDDATA;
2156  }
2157  for (i = 0; i < PALETTE_DELTA; i++)
2158  dp[i] = bytestream2_get_le16u(&ctx->gb);
2159  size -= PALETTE_DELTA * 2;
2160 
2161  if (size >= PALETTE_SIZE * 3) {
2162  for (i = 0; i < PALETTE_SIZE; i++)
2163  ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb);
2164  if (ctx->subversion < 2)
2165  ctx->pal[0] = 0xFFU << 24;
2166  }
2167  for (i = 0, j = 0; i < PALETTE_DELTA; i += 3, j++) {
2168  ctx->shift_pal[i + 0] = (((ctx->pal[j]) >> 16) & 0xFFU) << 7;
2169  ctx->shift_pal[i + 1] = (((ctx->pal[j]) >> 8) & 0xFFU) << 7;
2170  ctx->shift_pal[i + 2] = (((ctx->pal[j]) >> 0) & 0xFFU) << 7;
2171  }
2172  }
2173  return 0;
2174 }
2175 
2177 {
2178  uint16_t *frm = ctx->frm0;
2179  int x, y;
2180 
2181  if (bytestream2_get_bytes_left(&ctx->gb) < ctx->width * ctx->height * 2) {
2182  av_log(ctx->avctx, AV_LOG_ERROR, "Insufficient data for raw frame.\n");
2183  return AVERROR_INVALIDDATA;
2184  }
2185  for (y = 0; y < ctx->height; y++) {
2186  for (x = 0; x < ctx->width; x++)
2187  frm[x] = bytestream2_get_le16u(&ctx->gb);
2188  frm += ctx->pitch;
2189  }
2190  return 0;
2191 }
2192 
2193 /* BL16 pixel interpolation function, see tgsmush.dll c690 */
2194 static inline uint16_t bl16_c1_avg_col(uint16_t c1, uint16_t c2)
2195 {
2196  return (((c2 & 0x07e0) + (c1 & 0x07e0)) & 0x00fc0) |
2197  (((c2 & 0xf800) + (c1 & 0xf800)) & 0x1f000) |
2198  (((c2 & 0x001f) + (c1 & 0x001f))) >> 1;
2199 }
2200 
2201 /* Quarter-sized keyframe encoded as stream of 16bit pixel values. Interpolate
2202  * missing pixels by averaging the colors of immediate neighbours.
2203  * Identical to codec47_comp1() but with 16bit-pixels. tgsmush.dll c6f0
2204  */
2206 {
2207  uint16_t hh, hw, c1, c2, *dst1, *dst2;
2208 
2209  if (bytestream2_get_bytes_left(&ctx->gb) < ((ctx->width * ctx->height) / 2))
2210  return AVERROR_INVALIDDATA;
2211 
2212  hh = (ctx->height + 1) >> 1;
2213  dst1 = (uint16_t *)ctx->frm0 + ctx->pitch; /* start with line 1 */
2214  while (hh--) {
2215  hw = (ctx->width - 1) >> 1;
2216  c1 = bytestream2_get_le16u(&ctx->gb);
2217  dst1[0] = c1;
2218  dst1[1] = c1;
2219  dst2 = dst1 + 2;
2220  while (--hw) {
2221  c2 = bytestream2_get_le16u(&ctx->gb);
2222  *dst2++ = bl16_c1_avg_col(c1, c2);
2223  *dst2++ = c2;
2224  c1 = c2;
2225  }
2226  dst1 += ctx->pitch * 2; /* skip to overnext line */
2227  }
2228  /* line 0 is a copy of line 1 */
2229  memcpy(ctx->frm0, ctx->frm0 + ctx->pitch, ctx->pitch);
2230 
2231  /* complete the skipped lines by averaging from the pixels in the lines
2232  * above and below
2233  */
2234  dst1 = ctx->frm0 + (ctx->pitch * 2);
2235  hh = (ctx->height - 1) >> 1;
2236  while (hh--) {
2237  hw = ctx->width;
2238  dst2 = dst1;
2239  while (hw--) {
2240  c1 = *(dst2 - ctx->pitch); /* pixel from line above */
2241  c2 = *(dst2 + ctx->pitch); /* pixel from line below */
2242  *dst2++ = bl16_c1_avg_col(c1, c2);
2243  }
2244  dst1 += ctx->pitch * 2;
2245  }
2246  return 0;
2247 }
2248 
2249 static void copy_block(uint16_t *pdest, uint16_t *psrc, int block_size, ptrdiff_t pitch)
2250 {
2251  uint8_t *dst = (uint8_t *)pdest;
2252  uint8_t *src = (uint8_t *)psrc;
2253  ptrdiff_t stride = pitch * 2;
2254 
2255  switch (block_size) {
2256  case 2:
2257  copy_block4(dst, src, stride, stride, 2);
2258  break;
2259  case 4:
2260  copy_block8(dst, src, stride, stride, 4);
2261  break;
2262  case 8:
2263  copy_block16(dst, src, stride, stride, 8);
2264  break;
2265  }
2266 }
2267 
2268 static void fill_block(uint16_t *pdest, uint16_t color, int block_size, ptrdiff_t pitch)
2269 {
2270  int x, y;
2271 
2272  pitch -= block_size;
2273  for (y = 0; y < block_size; y++, pdest += pitch)
2274  for (x = 0; x < block_size; x++)
2275  *pdest++ = color;
2276 }
2277 
2278 static int draw_glyph(SANMVideoContext *ctx, uint16_t *dst, int index,
2279  uint16_t fg_color, uint16_t bg_color, int block_size,
2280  ptrdiff_t pitch)
2281 {
2282  int8_t *pglyph;
2283  uint16_t colors[2] = { fg_color, bg_color };
2284  int x, y;
2285 
2286  if (index >= NGLYPHS) {
2287  av_log(ctx->avctx, AV_LOG_ERROR, "Ignoring nonexistent glyph #%u.\n", index);
2288  return AVERROR_INVALIDDATA;
2289  }
2290 
2291  pglyph = block_size == 8 ? ctx->p8x8glyphs[index] : ctx->p4x4glyphs[index];
2292  pitch -= block_size;
2293 
2294  for (y = 0; y < block_size; y++, dst += pitch)
2295  for (x = 0; x < block_size; x++)
2296  *dst++ = colors[*pglyph++];
2297  return 0;
2298 }
2299 
2300 static int opcode_0xf7(SANMVideoContext *ctx, int cx, int cy, int block_size, ptrdiff_t pitch)
2301 {
2302  uint16_t *dst = ctx->frm0 + cx + cy * ctx->pitch;
2303 
2304  if (block_size == 2) {
2305  uint32_t indices;
2306 
2307  if (bytestream2_get_bytes_left(&ctx->gb) < 4)
2308  return AVERROR_INVALIDDATA;
2309 
2310  indices = bytestream2_get_le32u(&ctx->gb);
2311  dst[0] = ctx->codebook[indices & 0xFF];
2312  indices >>= 8;
2313  dst[1] = ctx->codebook[indices & 0xFF];
2314  indices >>= 8;
2315  dst[pitch] = ctx->codebook[indices & 0xFF];
2316  indices >>= 8;
2317  dst[pitch + 1] = ctx->codebook[indices & 0xFF];
2318  } else {
2319  uint16_t fgcolor, bgcolor;
2320  int glyph;
2321 
2322  if (bytestream2_get_bytes_left(&ctx->gb) < 3)
2323  return AVERROR_INVALIDDATA;
2324 
2325  glyph = bytestream2_get_byteu(&ctx->gb);
2326  bgcolor = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
2327  fgcolor = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
2328 
2329  draw_glyph(ctx, dst, glyph, fgcolor, bgcolor, block_size, pitch);
2330  }
2331  return 0;
2332 }
2333 
2334 static int opcode_0xf8(SANMVideoContext *ctx, int cx, int cy, int block_size, ptrdiff_t pitch)
2335 {
2336  uint16_t *dst = ctx->frm0 + cx + cy * ctx->pitch;
2337 
2338  if (block_size == 2) {
2339  if (bytestream2_get_bytes_left(&ctx->gb) < 8)
2340  return AVERROR_INVALIDDATA;
2341 
2342  dst[0] = bytestream2_get_le16u(&ctx->gb);
2343  dst[1] = bytestream2_get_le16u(&ctx->gb);
2344  dst[pitch] = bytestream2_get_le16u(&ctx->gb);
2345  dst[pitch + 1] = bytestream2_get_le16u(&ctx->gb);
2346  } else {
2347  uint16_t fgcolor, bgcolor;
2348  int glyph;
2349 
2350  if (bytestream2_get_bytes_left(&ctx->gb) < 5)
2351  return AVERROR_INVALIDDATA;
2352 
2353  glyph = bytestream2_get_byteu(&ctx->gb);
2354  bgcolor = bytestream2_get_le16u(&ctx->gb);
2355  fgcolor = bytestream2_get_le16u(&ctx->gb);
2356 
2357  draw_glyph(ctx, dst, glyph, fgcolor, bgcolor, block_size, pitch);
2358  }
2359  return 0;
2360 }
2361 
2362 static int good_mvec(SANMVideoContext *ctx, int cx, int cy, int mx, int my,
2363  int block_size)
2364 {
2365  int start_pos = cx + mx + (cy + my) * ctx->pitch;
2366  int end_pos = start_pos + (block_size - 1) * (ctx->pitch + 1);
2367 
2368  int good = start_pos >= 0 && end_pos < (ctx->buf_size >> 1);
2369 
2370  if (!good)
2371  av_log(ctx->avctx, AV_LOG_ERROR,
2372  "Ignoring invalid motion vector (%i, %i)->(%u, %u), block size = %u\n",
2373  cx + mx, cy + my, cx, cy, block_size);
2374 
2375  return good;
2376 }
2377 
2378 static int bl16_block(SANMVideoContext *ctx, int cx, int cy, int blk_size)
2379 {
2380  int16_t mx, my, index;
2381  int opcode;
2382 
2383  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
2384  return AVERROR_INVALIDDATA;
2385 
2386  opcode = bytestream2_get_byteu(&ctx->gb);
2387 
2388  switch (opcode) {
2389  default:
2390  mx = c47_mv[opcode][0];
2391  my = c47_mv[opcode][1];
2392 
2393  /* The original implementation of this codec precomputes a table
2394  * of int16_t of all motion vectors a for given image width.
2395  * For widths starting at 762 pixels, the calculation of
2396  * mv table indices 1+ and 255- overflow the int16_t, inverting the
2397  * sign of the offset. This is actively exploited in e.g. the
2398  * "jonesopn_8.snm" video of "Indiana Jones and the Infernal Machine".
2399  * Therefore let the overflow happen and extract x/y components from
2400  * the new value.
2401  */
2402  if (ctx->width > 761) {
2403  index = (int16_t)(my * ctx->width + mx);
2404  mx = index % ctx->width;
2405  my = index / ctx->width;
2406  }
2407  if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
2408  copy_block(ctx->frm0 + cx + ctx->pitch * cy,
2409  ctx->frm2 + cx + mx + ctx->pitch * (cy + my),
2410  blk_size, ctx->pitch);
2411  }
2412  break;
2413  case 0xF5:
2414  if (bytestream2_get_bytes_left(&ctx->gb) < 2)
2415  return AVERROR_INVALIDDATA;
2416  index = bytestream2_get_le16u(&ctx->gb);
2417 
2418  mx = index % ctx->width;
2419  my = index / ctx->width;
2420 
2421  if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
2422  copy_block(ctx->frm0 + cx + ctx->pitch * cy,
2423  ctx->frm2 + cx + mx + ctx->pitch * (cy + my),
2424  blk_size, ctx->pitch);
2425  }
2426  break;
2427  case 0xF6:
2428  copy_block(ctx->frm0 + cx + ctx->pitch * cy,
2429  ctx->frm1 + cx + ctx->pitch * cy,
2430  blk_size, ctx->pitch);
2431  break;
2432  case 0xF7:
2433  opcode_0xf7(ctx, cx, cy, blk_size, ctx->pitch);
2434  break;
2435 
2436  case 0xF8:
2437  opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch);
2438  break;
2439  case 0xF9:
2440  case 0xFA:
2441  case 0xFB:
2442  case 0xFC:
2443  fill_block(ctx->frm0 + cx + cy * ctx->pitch,
2444  ctx->small_codebook[opcode - 0xf9], blk_size, ctx->pitch);
2445  break;
2446  case 0xFD:
2447  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
2448  return AVERROR_INVALIDDATA;
2449  fill_block(ctx->frm0 + cx + cy * ctx->pitch,
2450  ctx->codebook[bytestream2_get_byteu(&ctx->gb)], blk_size, ctx->pitch);
2451  break;
2452  case 0xFE:
2453  if (bytestream2_get_bytes_left(&ctx->gb) < 2)
2454  return AVERROR_INVALIDDATA;
2455  fill_block(ctx->frm0 + cx + cy * ctx->pitch,
2456  bytestream2_get_le16u(&ctx->gb), blk_size, ctx->pitch);
2457  break;
2458  case 0xFF:
2459  if (blk_size == 2) {
2460  opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch);
2461  } else {
2462  blk_size >>= 1;
2463  if (bl16_block(ctx, cx, cy, blk_size))
2464  return AVERROR_INVALIDDATA;
2465  if (bl16_block(ctx, cx + blk_size, cy, blk_size))
2466  return AVERROR_INVALIDDATA;
2467  if (bl16_block(ctx, cx, cy + blk_size, blk_size))
2468  return AVERROR_INVALIDDATA;
2469  if (bl16_block(ctx, cx + blk_size, cy + blk_size, blk_size))
2470  return AVERROR_INVALIDDATA;
2471  }
2472  break;
2473  }
2474  return 0;
2475 }
2476 
2478 {
2479  int cx, cy, ret;
2480 
2481  for (cy = 0; cy < ctx->aligned_height; cy += 8)
2482  for (cx = 0; cx < ctx->aligned_width; cx += 8)
2483  if (ret = bl16_block(ctx, cx, cy, 8))
2484  return ret;
2485 
2486  return 0;
2487 }
2488 
2489 static int bl16_decode_5(SANMVideoContext *ctx, int rle_size)
2490 {
2491 #if HAVE_BIGENDIAN
2492  uint16_t *frm;
2493  int npixels;
2494 #endif
2495  uint8_t *dst = (uint8_t*)ctx->frm0;
2496 
2497  if (rle_decode(ctx, &ctx->gb, dst, rle_size))
2498  return AVERROR_INVALIDDATA;
2499 
2500 #if HAVE_BIGENDIAN
2501  npixels = ctx->npixels;
2502  frm = ctx->frm0;
2503  while (npixels--) {
2504  *frm = av_bswap16(*frm);
2505  frm++;
2506  }
2507 #endif
2508 
2509  return 0;
2510 }
2511 
2513 {
2514  int npixels = ctx->npixels;
2515  uint16_t *frm = ctx->frm0;
2516 
2517  if (bytestream2_get_bytes_left(&ctx->gb) < npixels) {
2518  av_log(ctx->avctx, AV_LOG_ERROR, "Insufficient data for frame.\n");
2519  return AVERROR_INVALIDDATA;
2520  }
2521  while (npixels--)
2522  *frm++ = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
2523 
2524  return 0;
2525 }
2526 
2527 /* Quarter-sized keyframe encoded as stream of codebook indices. Interpolate
2528  * missing pixels by averaging the colors of immediate neighbours.
2529  * Identical to codec47_comp1(), but without the interpolation table.
2530  * tgsmush.dll c6f0
2531  */
2533 {
2534  uint16_t hh, hw, c1, c2, *dst1, *dst2;
2535 
2536  if (bytestream2_get_bytes_left(&ctx->gb) < ((ctx->width * ctx->height) / 4))
2537  return AVERROR_INVALIDDATA;
2538 
2539  hh = (ctx->height + 1) >> 1;
2540  dst1 = (uint16_t *)ctx->frm0 + ctx->pitch; /* start with line 1 */
2541  while (hh--) {
2542  hw = (ctx->width - 1) >> 1;
2543  c1 = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
2544  dst1[0] = c1; /* leftmost 2 pixels of a row are identical */
2545  dst1[1] = c1;
2546  dst2 = dst1 + 2;
2547  while (--hw) {
2548  c2 = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
2549  *dst2++ = bl16_c1_avg_col(c1, c2);
2550  *dst2++ = c2;
2551  c1 = c2;
2552  }
2553  dst1 += ctx->pitch * 2; /* skip to overnext line */
2554  }
2555  /* line 0 is a copy of line 1 */
2556  memcpy(ctx->frm0, ctx->frm0 + ctx->pitch, ctx->pitch);
2557 
2558  /* complete the skipped lines by averaging from the pixels in the lines
2559  * above and below.
2560  */
2561  dst1 = ctx->frm0 + (ctx->pitch * 2);
2562  hh = (ctx->height - 1) >> 1;
2563  while (hh--) {
2564  hw = ctx->width;
2565  dst2 = dst1;
2566  while (hw--) {
2567  c1 = *(dst2 - ctx->pitch); /* pixel from line above */
2568  c2 = *(dst2 + ctx->pitch); /* pixel from line below */
2569  *dst2++ = bl16_c1_avg_col(c1, c2);
2570  }
2571  dst1 += ctx->pitch * 2;
2572  }
2573  return 0;
2574 }
2575 
2577 {
2578  uint16_t *pdest = ctx->frm0;
2579  uint8_t *rsrc;
2580  long npixels = ctx->npixels;
2581 
2582  av_fast_malloc(&ctx->rle_buf, &ctx->rle_buf_size, npixels);
2583  if (!ctx->rle_buf) {
2584  av_log(ctx->avctx, AV_LOG_ERROR, "RLE buffer allocation failed.\n");
2585  return AVERROR(ENOMEM);
2586  }
2587  rsrc = ctx->rle_buf;
2588 
2589  if (rle_decode(ctx, &ctx->gb, rsrc, npixels))
2590  return AVERROR_INVALIDDATA;
2591 
2592  while (npixels--)
2593  *pdest++ = ctx->codebook[*rsrc++];
2594 
2595  return 0;
2596 }
2597 
2598 static void fill_frame(uint16_t *pbuf, int buf_size, uint16_t color)
2599 {
2600  if (buf_size--) {
2601  *pbuf++ = color;
2602  av_memcpy_backptr((uint8_t*)pbuf, 2, 2*buf_size);
2603  }
2604 }
2605 
2606 static int copy_output(SANMVideoContext *ctx, int sanm)
2607 {
2608  uint8_t *dst;
2609  const uint8_t *src = sanm ? (uint8_t *)ctx->frm0 : (uint8_t *)ctx->fbuf;
2610  int ret, height = ctx->height;
2611  ptrdiff_t dstpitch, srcpitch = ctx->pitch * (sanm ? sizeof(ctx->frm0[0]) : 1);
2612 
2613  if ((ret = ff_get_buffer(ctx->avctx, ctx->frame, 0)) < 0)
2614  return ret;
2615 
2616  dst = ctx->frame->data[0];
2617  dstpitch = ctx->frame->linesize[0];
2618 
2619  while (height--) {
2620  memcpy(dst, src, srcpitch);
2621  src += srcpitch;
2622  dst += dstpitch;
2623  }
2624 
2625  return 0;
2626 }
2627 
2628 static int decode_bl16(AVCodecContext *avctx,int *got_frame_ptr)
2629 {
2630  SANMVideoContext *ctx = avctx->priv_data;
2631  int i, ret, w, h, seq_num, codec, bg_color, rle_output_size, rcode;
2632 
2633  if ((ret = bytestream2_get_bytes_left(&ctx->gb)) < 560) {
2634  av_log(ctx->avctx, AV_LOG_ERROR, "Input frame too short (%d bytes).\n",
2635  ret);
2636  return AVERROR_INVALIDDATA;
2637  }
2638  bytestream2_skip(&ctx->gb, 8); // skip pad
2639 
2640  w = bytestream2_get_le32u(&ctx->gb);
2641  h = bytestream2_get_le32u(&ctx->gb);
2642 
2643  if (w != ctx->width || h != ctx->height) {
2644  avpriv_report_missing_feature(ctx->avctx, "Variable size frames");
2645  return AVERROR_PATCHWELCOME;
2646  }
2647 
2648  seq_num = bytestream2_get_le16u(&ctx->gb);
2649  codec = bytestream2_get_byteu(&ctx->gb);
2650  rcode = bytestream2_get_byteu(&ctx->gb);
2651 
2652  bytestream2_skip(&ctx->gb, 4); // skip pad
2653 
2654  for (i = 0; i < 4; i++)
2655  ctx->small_codebook[i] = bytestream2_get_le16u(&ctx->gb);
2656  bg_color = bytestream2_get_le16u(&ctx->gb);
2657 
2658  bytestream2_skip(&ctx->gb, 2); // skip pad
2659 
2660  rle_output_size = bytestream2_get_le32u(&ctx->gb);
2661  if (rle_output_size > w * ctx->aligned_height * 2) {
2662  av_log(avctx, AV_LOG_WARNING, "bl16 rle size too large, truncated: %d\n",
2663  rle_output_size);
2664  rle_output_size = w * ctx->aligned_height * 2;
2665  }
2666 
2667  for (i = 0; i < 256; i++)
2668  ctx->codebook[i] = bytestream2_get_le16u(&ctx->gb);
2669 
2670  bytestream2_skip(&ctx->gb, 8); // skip pad
2671 
2672  if (seq_num == 0) {
2673  ctx->frame->flags |= AV_FRAME_FLAG_KEY;
2674  ctx->frame->pict_type = AV_PICTURE_TYPE_I;
2675  fill_frame(ctx->frm1, ctx->npixels, bg_color);
2676  fill_frame(ctx->frm2, ctx->npixels, bg_color);
2677  } else {
2678  ctx->frame->flags &= ~AV_FRAME_FLAG_KEY;
2679  ctx->frame->pict_type = AV_PICTURE_TYPE_P;
2680  }
2681 
2682  ret = 0;
2683  switch (codec) {
2684  case 0: ret = bl16_decode_0(ctx); break;
2685  case 1: ret = bl16_decode_1(ctx); break;
2686  case 2: ret = bl16_decode_2(ctx); break;
2687  case 3: memcpy(ctx->frm0, ctx->frm2, ctx->frm2_size); break;
2688  case 4: memcpy(ctx->frm0, ctx->frm1, ctx->frm1_size); break;
2689  case 5: ret = bl16_decode_5(ctx, rle_output_size); break;
2690  case 6: ret = bl16_decode_6(ctx); break;
2691  case 7: ret = bl16_decode_7(ctx); break;
2692  case 8: ret = bl16_decode_8(ctx); break;
2693  default:
2694  avpriv_request_sample(ctx->avctx, "Unknown/unsupported compression type %d", codec);
2695  return AVERROR_PATCHWELCOME;
2696  }
2697 
2698  if (ret) {
2699  av_log(avctx, AV_LOG_ERROR,
2700  "Subcodec %d: error decoding frame.\n", codec);
2701  return ret;
2702  }
2703 
2704  ret = copy_output(ctx, 1);
2705  if (rcode)
2706  rotate_bufs(ctx, rcode);
2707  if (ret)
2708  return ret;
2709 
2710  *got_frame_ptr = 1;
2711  return 0;
2712 }
2713 
2714 static int decode_anim(AVCodecContext *avctx, int *got_frame_ptr)
2715 {
2716  SANMVideoContext *ctx = avctx->priv_data;
2717  int i, ret, to_store = 0, have_img = 0;
2718 
2719  ctx->first_fob = 1;
2720  while (bytestream2_get_bytes_left(&ctx->gb) >= 8) {
2721  uint32_t sig, size;
2722  int pos;
2723 
2724  sig = bytestream2_get_be32u(&ctx->gb);
2725  size = bytestream2_get_be32u(&ctx->gb);
2726  pos = bytestream2_tell(&ctx->gb);
2727 
2728  if (bytestream2_get_bytes_left(&ctx->gb) < size) {
2729  av_log(avctx, AV_LOG_ERROR, "Incorrect chunk size %"PRIu32".\n", size);
2730  break;
2731  }
2732  switch (sig) {
2733  case MKBETAG('N', 'P', 'A', 'L'):
2734  if (size != PALETTE_SIZE * 3) {
2735  av_log(avctx, AV_LOG_ERROR,
2736  "Incorrect palette block size %"PRIu32".\n", size);
2737  return AVERROR_INVALIDDATA;
2738  }
2739  for (i = 0; i < PALETTE_SIZE; i++)
2740  ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb);
2741  if (ctx->subversion < 2)
2742  ctx->pal[0] = 0xFFU << 24;
2743  break;
2744  case MKBETAG('F', 'O', 'B', 'J'):
2745  if (size < 16)
2746  return AVERROR_INVALIDDATA;
2748  bytestream2_init(&fc, ctx->gb.buffer, size);
2749  if (ret = process_frame_obj(ctx, &fc, 0, 0)) {
2750  return ret;
2751  }
2752  have_img = 1;
2753 
2754  /* STOR: for ANIMv0/1 store the whole FOBJ datablock, as it
2755  * needs to be replayed on FTCH, since none of the codecs
2756  * it uses work on the full buffer.
2757  * For ANIMv2, it's enough to store the current framebuffer.
2758  */
2759  if (to_store) {
2760  to_store = 0;
2761  if (ctx->subversion < 2) {
2762  if (size <= ctx->stored_frame_size) {
2763  bytestream2_seek(&fc, 0, SEEK_SET);
2764  bytestream2_get_bufferu(&fc, ctx->stored_frame, size);
2765  ctx->stor_size = size;
2766  } else {
2767  av_log(avctx, AV_LOG_ERROR, "FOBJ too large for STOR\n");
2768  ret = AVERROR(ENOMEM);
2769  }
2770  } else {
2771  memcpy(ctx->stored_frame, ctx->fbuf, ctx->buf_size);
2772  ctx->stor_size = ctx->buf_size;
2773  }
2774  }
2775  bytestream2_skip(&ctx->gb, size);
2776  break;
2777  case MKBETAG('X', 'P', 'A', 'L'):
2778  if (ret = process_xpal(ctx, size))
2779  return ret;
2780  break;
2781  case MKBETAG('S', 'T', 'O', 'R'):
2782  to_store = 1;
2783  break;
2784  case MKBETAG('F', 'T', 'C', 'H'):
2785  if (ctx->subversion < 2) {
2786  if ((ret = process_ftch(ctx, size)) < 0)
2787  return ret;
2788  have_img = (ret == 0) ? 1 : 0;
2789  } else {
2790  if (ctx->stor_size > 0) {
2791  memcpy(ctx->fbuf, ctx->stored_frame, ctx->buf_size);
2792  have_img = 1;
2793  }
2794  }
2795  break;
2796  default:
2797  bytestream2_skip(&ctx->gb, size);
2798  av_log(avctx, AV_LOG_DEBUG,
2799  "Unknown/unsupported chunk %"PRIx32".\n", sig);
2800  break;
2801  }
2802 
2803  /* the sizes of chunks are usually a multiple of 2. However
2804  * there are a few unaligned FOBJs in RA1 L2PLAY.ANM only (looks
2805  * like a game bug) and IACT audio chunks which have odd sizes
2806  * but are padded with a zero byte.
2807  */
2808  bytestream2_seek(&ctx->gb, pos + size, SEEK_SET);
2809  if ((pos + size) & 1) {
2810  if (bytestream2_peek_byte(&ctx->gb) == 0)
2811  bytestream2_skip(&ctx->gb, 1);
2812  }
2813  }
2814 
2815  if (have_img) {
2816  if ((ret = copy_output(ctx, 0)))
2817  return ret;
2818  memcpy(ctx->frame->data[1], ctx->pal, 1024);
2819  *got_frame_ptr = 1;
2820  }
2821  return 0;
2822 }
2823 
2825  int *got_frame_ptr, AVPacket *pkt)
2826 {
2827  SANMVideoContext *ctx = avctx->priv_data;
2828  int ret;
2829 
2830  ctx->frame = frame;
2831  bytestream2_init(&ctx->gb, pkt->data, pkt->size);
2832 
2833  if (!ctx->version) {
2834  if ((ret = decode_anim(avctx, got_frame_ptr)))
2835  return ret;
2836  } else {
2837  if ((ret = decode_bl16(avctx, got_frame_ptr)))
2838  return ret;
2839  }
2840  return pkt->size;
2841 }
2842 
2844  .p.name = "sanm",
2845  CODEC_LONG_NAME("LucasArts SANM/Smush video"),
2846  .p.type = AVMEDIA_TYPE_VIDEO,
2847  .p.id = AV_CODEC_ID_SANM,
2848  .priv_data_size = sizeof(SANMVideoContext),
2849  .init = decode_init,
2850  .close = decode_end,
2852  .p.capabilities = AV_CODEC_CAP_DR1,
2853 };
SANMVideoContext::width
int width
Definition: sanm.c:274
flags
const SwsFlags flags[]
Definition: swscale.c:61
rle_decode
static int rle_decode(SANMVideoContext *ctx, GetByteContext *gb, uint8_t *dst, const int out_size)
Definition: sanm.c:744
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:216
AV_CODEC_ID_SANM
@ AV_CODEC_ID_SANM
Definition: codec_id.h:236
SANMVideoContext::fbuf_size
uint32_t fbuf_size
Definition: sanm.c:281
bl16_decode_6
static int bl16_decode_6(SANMVideoContext *ctx)
Definition: sanm.c:2512
codec47_comp1
static void codec47_comp1(GetByteContext *gb, uint8_t *dst_in, int width, const int height, const ptrdiff_t stride, const uint8_t *itbl)
Definition: sanm.c:1505
BOTTOM_EDGE
@ BOTTOM_EDGE
Definition: sanm.c:306
SANMVideoContext::rle_buf
uint8_t * rle_buf
Definition: sanm.c:285
old_codec37
static int old_codec37(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int width, int height)
Definition: sanm.c:1218
fill_block
static void fill_block(uint16_t *pdest, uint16_t color, int block_size, ptrdiff_t pitch)
Definition: sanm.c:2268
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
bytestream2_get_bytes_left
static av_always_inline int bytestream2_get_bytes_left(const GetByteContext *g)
Definition: bytestream.h:158
make_glyphs
static void make_glyphs(int8_t *pglyphs, const int8_t *xvec, const int8_t *yvec, const int side_length)
Construct glyphs by iterating through vector coordinates.
Definition: sanm.c:384
blt_mask
static void blt_mask(uint8_t *dst, const uint8_t *src, int16_t left, int16_t top, uint16_t srcxoff, uint16_t srcyoff, uint16_t srcwidth, uint16_t srcheight, const uint16_t srcpitch, const uint16_t dstpitch, const uint16_t dstheight, int32_t size, const uint8_t skipcolor)
Definition: sanm.c:1084
color
Definition: vf_paletteuse.c:513
GetByteContext
Definition: bytestream.h:33
SANMVideoContext::pal
uint32_t pal[PALETTE_SIZE]
Definition: sanm.c:270
bytestream2_tell
static av_always_inline int bytestream2_tell(const GetByteContext *g)
Definition: bytestream.h:192
bl16_decode_5
static int bl16_decode_5(SANMVideoContext *ctx, int rle_size)
Definition: sanm.c:2489
src1
const pixel * src1
Definition: h264pred_template.c:420
SANMVideoContext::stored_frame
uint8_t * stored_frame
Definition: sanm.c:280
SANMVideoContext::aligned_height
int aligned_height
Definition: sanm.c:275
SANMVideoContext::p4x4glyphs
int8_t p4x4glyphs[NGLYPHS][16]
Definition: sanm.c:293
good_mvec
static int good_mvec(SANMVideoContext *ctx, int cx, int cy, int mx, int my, int block_size)
Definition: sanm.c:2362
mask
int mask
Definition: mediacodecdec_common.c:154
out_size
int out_size
Definition: movenc.c:56
blt_solid
static void blt_solid(uint8_t *dst, const uint8_t *src, int16_t left, int16_t top, uint16_t srcxoff, uint16_t srcyoff, uint16_t srcwidth, uint16_t srcheight, const uint16_t srcpitch, const uint16_t dstpitch, const uint16_t dstheight, int32_t size)
Definition: sanm.c:1032
old_codec31
static int old_codec31(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int width, int height, int p1, int opaque)
Definition: sanm.c:948
bytestream2_seek
static av_always_inline int bytestream2_seek(GetByteContext *g, int offset, int whence)
Definition: bytestream.h:212
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:427
w
uint8_t w
Definition: llviddspenc.c:38
AVPacket::data
uint8_t * data
Definition: packet.h:558
decode_end
static av_cold int decode_end(AVCodecContext *avctx)
Definition: sanm.c:668
bl16_decode_1
static int bl16_decode_1(SANMVideoContext *ctx)
Definition: sanm.c:2205
bl16_decode_0
static int bl16_decode_0(SANMVideoContext *ctx)
Definition: sanm.c:2176
interp_point
static void interp_point(int8_t *points, int x0, int y0, int x1, int y1, int pos, int npoints)
Definition: sanm.c:364
FFCodec
Definition: codec_internal.h:127
copy_block8
static void copy_block8(uint8_t *dst, const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t srcStride, int h)
Definition: copy_block.h:47
bl16_block
static int bl16_block(SANMVideoContext *ctx, int cx, int cy, int blk_size)
Definition: sanm.c:2378
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
c1
static const uint64_t c1
Definition: murmur3.c:52
ff_set_dimensions
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Check that the provided frame dimensions are valid and set them on the codec context.
Definition: utils.c:91
ff_sanm_decoder
const FFCodec ff_sanm_decoder
Definition: sanm.c:2843
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
bit
#define bit(string, value)
Definition: cbs_mpeg2.c:56
c48_invalid_mv
static int c48_invalid_mv(int x, int y, const uint16_t w, int h, int blocksize, int mvofs)
Definition: sanm.c:1649
px
#define px
Definition: ops_tmpl_float.c:35
close
static av_cold void close(AVCodecParserContext *s)
Definition: apv_parser.c:135
bytestream2_skip
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:168
SANMVideoContext::frame
AVFrame * frame
Definition: sanm.c:278
mx
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t mx
Definition: dsp.h:57
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:131
copy_output
static int copy_output(SANMVideoContext *ctx, int sanm)
Definition: sanm.c:2606
LEFT_EDGE
@ LEFT_EDGE
Definition: sanm.c:303
glyph8_x
static const int8_t glyph8_x[GLYPH_COORD_VECT_SIZE]
Definition: sanm.c:45
SANMVideoContext::gb
GetByteContext gb
Definition: sanm.c:267
destroy_buffers
static void destroy_buffers(SANMVideoContext *ctx)
Definition: sanm.c:449
loop
static int loop
Definition: ffplay.c:335
SANMVideoContext::small_codebook
uint16_t small_codebook[4]
Definition: sanm.c:291
DIR_LEFT
@ DIR_LEFT
Definition: sanm.c:311
which_edge
static enum GlyphEdge which_edge(int x, int y, int edge_size)
Return enum GlyphEdge of box where point (x, y) lies.
Definition: sanm.c:325
NO_EDGE
@ NO_EDGE
Definition: sanm.c:307
SANMVideoContext::stor_size
uint32_t stor_size
Definition: sanm.c:282
TOP_EDGE
@ TOP_EDGE
Definition: sanm.c:304
avassert.h
SANMVideoContext::have_dimensions
int have_dimensions
Definition: sanm.c:269
pkt
AVPacket * pkt
Definition: movenc.c:60
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
av_cold
#define av_cold
Definition: attributes.h:106
AV_FRAME_FLAG_KEY
#define AV_FRAME_FLAG_KEY
A flag to mark frames that are keyframes.
Definition: frame.h:642
bl16_decode_7
static int bl16_decode_7(SANMVideoContext *ctx)
Definition: sanm.c:2532
av_memcpy_backptr
void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
Overlapping memcpy() implementation.
Definition: mem.c:447
clip
clip
Definition: af_crystalizer.c:122
AVCodecContext::extradata_size
int extradata_size
Definition: avcodec.h:515
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:346
process_frame_obj
static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb, int xoff, int yoff)
Definition: sanm.c:1949
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1415
c48_4to8
static void c48_4to8(uint8_t *dst, const uint8_t *src, const uint16_t w)
Definition: sanm.c:1634
old_codec47
static int old_codec47(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int width, int height)
Definition: sanm.c:1538
GetByteContext::buffer
const uint8_t * buffer
Definition: bytestream.h:34
fc
#define fc(width, name, range_min, range_max)
Definition: cbs_av1.c:494
SANMVideoContext::npixels
long npixels
Definition: sanm.c:288
bits
uint8_t bits
Definition: vp3data.h:128
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:41
old_codec2
static int old_codec2(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int width, int height)
Definition: sanm.c:1014
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:231
opcode_0xf8
static int opcode_0xf8(SANMVideoContext *ctx, int cx, int cy, int block_size, ptrdiff_t pitch)
Definition: sanm.c:2334
ctx
AVFormatContext * ctx
Definition: movenc.c:49
SANMVideoContext::stored_frame_size
uint32_t stored_frame_size
Definition: sanm.c:283
decode.h
AV_RL16
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_RL16
Definition: bytestream.h:94
codec47_read_interptable
static void codec47_read_interptable(GetByteContext *gb, uint8_t *itbl)
Definition: sanm.c:1489
bl16_decode_2
static int bl16_decode_2(SANMVideoContext *ctx)
Definition: sanm.c:2477
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:331
my
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t my
Definition: dsp.h:57
FFABS
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:74
if
if(ret)
Definition: filter_design.txt:179
GlyphEdge
GlyphEdge
Definition: sanm.c:302
init_sizes
static void init_sizes(SANMVideoContext *ctx, int width, int height)
Definition: sanm.c:436
copy_block16
static void copy_block16(uint8_t *dst, const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t srcStride, int h)
Definition: copy_block.h:68
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:64
run
uint8_t run
Definition: svq3.c:207
SANMVideoContext::aligned_width
int aligned_width
Definition: sanm.c:275
old_codec23
static int old_codec23(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int width, int height, uint8_t param, uint16_t param2)
Definition: sanm.c:770
SANMVideoContext::avctx
AVCodecContext * avctx
Definition: sanm.c:266
SANMVideoContext::subversion
int subversion
Definition: sanm.c:269
draw_glyph
static int draw_glyph(SANMVideoContext *ctx, uint16_t *dst, int index, uint16_t fg_color, uint16_t bg_color, int block_size, ptrdiff_t pitch)
Definition: sanm.c:2278
bl16_decode_8
static int bl16_decode_8(SANMVideoContext *ctx)
Definition: sanm.c:2576
AV_PICTURE_TYPE_I
@ AV_PICTURE_TYPE_I
Intra.
Definition: avutil.h:278
PALETTE_SIZE
#define PALETTE_SIZE
Definition: sanm.c:34
SANMVideoContext::frm1_size
uint32_t frm1_size
Definition: sanm.c:281
SANMVideoContext::frm1
uint16_t * frm1
Definition: sanm.c:279
rotate_bufs
static void rotate_bufs(SANMVideoContext *ctx, int rotate_code)
Definition: sanm.c:615
SANMVideoContext::c47itbl
uint8_t c47itbl[0x10000]
Definition: sanm.c:295
index
int index
Definition: gxfenc.c:90
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
codec4_gen_tiles
static void codec4_gen_tiles(SANMVideoContext *ctx, uint16_t param1)
Definition: sanm.c:548
glyph4_y
static const int8_t glyph4_y[GLYPH_COORD_VECT_SIZE]
Definition: sanm.c:41
NGLYPHS
#define NGLYPHS
Definition: sanm.c:32
SANMVideoContext::frm2_size
uint32_t frm2_size
Definition: sanm.c:281
ff_get_buffer
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1720
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:368
AV_CODEC_CAP_DR1
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:52
AVPacket::size
int size
Definition: packet.h:559
SANMVideoContext
Definition: sanm.c:265
height
#define height
Definition: dsp.h:89
codec37_mv
static void codec37_mv(uint8_t *dst, const uint8_t *src, int height, int stride, int x, int y)
Definition: sanm.c:1199
codec_internal.h
glyph8_y
static const int8_t glyph8_y[GLYPH_COORD_VECT_SIZE]
Definition: sanm.c:49
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
size
int size
Definition: twinvq_data.h:10344
color
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:97
MKBETAG
#define MKBETAG(a, b, c, d)
Definition: macros.h:56
avpriv_report_missing_feature
void avpriv_report_missing_feature(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
SANMVideoContext::version
int version
Definition: sanm.c:269
bl16_c1_avg_col
static uint16_t bl16_c1_avg_col(uint16_t c1, uint16_t c2)
Definition: sanm.c:2194
SANMVideoContext::frm0
uint16_t * frm0
Definition: sanm.c:279
c47_mv
static const int8_t c47_mv[256][2]
Definition: sanm.c:54
SANMVideoContext::c4param
uint16_t c4param
Definition: sanm.c:298
SANMVideoContext::c23lut
uint8_t c23lut[256]
Definition: sanm.c:296
old_codec4
static int old_codec4(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int w, int h, uint8_t param, uint16_t param2, int codec)
Definition: sanm.c:677
decode_init
static av_cold int decode_init(AVCodecContext *avctx)
Definition: sanm.c:622
xf
#define xf(width, name, var, range_min, range_max, subs,...)
Definition: cbs_av1.c:622
PALETTE_DELTA
#define PALETTE_DELTA
Definition: sanm.c:35
copy_block4
static void copy_block4(uint8_t *dst, const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t srcStride, int h)
Definition: copy_block.h:37
av_assert2
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:68
old_codec20
static int old_codec20(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, const int w, const int h)
Definition: sanm.c:1190
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
code
and forward the test the status of outputs and forward it to the corresponding return FFERROR_NOT_READY If the filters stores internally one or a few frame for some it can consider them to be part of the FIFO and delay acknowledging a status change accordingly Example code
Definition: filter_design.txt:178
AV_FRAME_FLAG_CORRUPT
#define AV_FRAME_FLAG_CORRUPT
The frame data may be corrupted, e.g.
Definition: frame.h:638
fill_frame
static void fill_frame(uint16_t *pbuf, int buf_size, uint16_t color)
Definition: sanm.c:2598
copy_block.h
copy_block
static void copy_block(uint16_t *pdest, uint16_t *psrc, int block_size, ptrdiff_t pitch)
Definition: sanm.c:2249
AVCodecContext::extradata
uint8_t * extradata
Out-of-band global headers that may be used by some codecs.
Definition: avcodec.h:514
src2
const pixel * src2
Definition: h264pred_template.c:421
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
process_xpal
static int process_xpal(SANMVideoContext *ctx, int size)
Definition: sanm.c:2129
SANMVideoContext::shift_pal
int16_t shift_pal[PALETTE_DELTA]
Definition: sanm.c:271
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:179
SANMVideoContext::fbuf
uint16_t * fbuf
Definition: sanm.c:279
SANMVideoContext::first_fob
int first_fob
Definition: sanm.c:269
len
int len
Definition: vorbis_enc_data.h:426
AVCodecContext::height
int height
Definition: avcodec.h:592
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:631
decode_anim
static int decode_anim(AVCodecContext *avctx, int *got_frame_ptr)
Definition: sanm.c:2714
AV_PIX_FMT_RGB565
#define AV_PIX_FMT_RGB565
Definition: pixfmt.h:526
avcodec.h
stride
#define stride
Definition: h264pred_template.c:536
SANMVideoContext::codebook
uint16_t codebook[256]
Definition: sanm.c:290
GlyphDir
GlyphDir
Definition: sanm.c:310
AV_PIX_FMT_PAL8
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:84
DIR_DOWN
@ DIR_DOWN
Definition: sanm.c:314
ret
ret
Definition: filter_design.txt:187
glyph4_x
static const int8_t glyph4_x[GLYPH_COORD_VECT_SIZE]
Definition: sanm.c:37
FFSWAP
#define FFSWAP(type, a, b)
Definition: macros.h:52
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:265
SANMVideoContext::frm2
uint16_t * frm2
Definition: sanm.c:279
DIR_RIGHT
@ DIR_RIGHT
Definition: sanm.c:313
pos
unsigned int pos
Definition: spdifenc.c:414
decode_bl16
static int decode_bl16(AVCodecContext *avctx, int *got_frame_ptr)
Definition: sanm.c:2628
c37_mv
static const int8_t c37_mv[]
Definition: sanm.c:109
flag
#define flag(name)
Definition: cbs_av1.c:496
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
left
Tag MUST be and< 10hcoeff half pel interpolation filter coefficients, hcoeff[0] are the 2 middle coefficients[1] are the next outer ones and so on, resulting in a filter like:...eff[2], hcoeff[1], hcoeff[0], hcoeff[0], hcoeff[1], hcoeff[2] ... the sign of the coefficients is not explicitly stored but alternates after each coeff and coeff[0] is positive, so ...,+,-,+,-,+,+,-,+,-,+,... hcoeff[0] is not explicitly stored but found by subtracting the sum of all stored coefficients with signs from 32 hcoeff[0]=32 - hcoeff[1] - hcoeff[2] - ... a good choice for hcoeff and htaps is htaps=6 hcoeff={40,-10, 2} an alternative which requires more computations at both encoder and decoder side and may or may not be better is htaps=8 hcoeff={42,-14, 6,-2}ref_frames minimum of the number of available reference frames and max_ref_frames for example the first frame after a key frame always has ref_frames=1spatial_decomposition_type wavelet type 0 is a 9/7 symmetric compact integer wavelet 1 is a 5/3 symmetric compact integer wavelet others are reserved stored as delta from last, last is reset to 0 if always_reset||keyframeqlog quality(logarithmic quantizer scale) stored as delta from last, last is reset to 0 if always_reset||keyframemv_scale stored as delta from last, last is reset to 0 if always_reset||keyframe FIXME check that everything works fine if this changes between framesqbias dequantization bias stored as delta from last, last is reset to 0 if always_reset||keyframeblock_max_depth maximum depth of the block tree stored as delta from last, last is reset to 0 if always_reset||keyframequant_table quantization tableHighlevel bitstream structure:==============================--------------------------------------------|Header|--------------------------------------------|------------------------------------|||Block0||||split?||||yes no||||......... intra?||||:Block01 :yes no||||:Block02 :....... ..........||||:Block03 ::y DC ::ref index:||||:Block04 ::cb DC ::motion x :||||......... :cr DC ::motion y :||||....... ..........|||------------------------------------||------------------------------------|||Block1|||...|--------------------------------------------|------------ ------------ ------------|||Y subbands||Cb subbands||Cr subbands||||--- ---||--- ---||--- ---|||||LL0||HL0||||LL0||HL0||||LL0||HL0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||LH0||HH0||||LH0||HH0||||LH0||HH0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HL1||LH1||||HL1||LH1||||HL1||LH1|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HH1||HL2||||HH1||HL2||||HH1||HL2|||||...||...||...|||------------ ------------ ------------|--------------------------------------------Decoding process:=================------------|||Subbands|------------||||------------|Intra DC||||LL0 subband prediction ------------|\ Dequantization ------------------- \||Reference frames|\ IDWT|------- -------|Motion \|||Frame 0||Frame 1||Compensation . OBMC v -------|------- -------|--------------. \------> Frame n output Frame Frame<----------------------------------/|...|------------------- Range Coder:============Binary Range Coder:------------------- The implemented range coder is an adapted version based upon "Range encoding: an algorithm for removing redundancy from a digitised message." by G. N. N. Martin. The symbols encoded by the Snow range coder are bits(0|1). The associated probabilities are not fix but change depending on the symbol mix seen so far. bit seen|new state ---------+----------------------------------------------- 0|256 - state_transition_table[256 - old_state];1|state_transition_table[old_state];state_transition_table={ 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202, 202, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 215, 215, 216, 217, 218, 219, 220, 220, 222, 223, 224, 225, 226, 227, 227, 229, 229, 230, 231, 232, 234, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 0, 0, 0, 0, 0, 0, 0};FIXME Range Coding of integers:------------------------- FIXME Neighboring Blocks:===================left and top are set to the respective blocks unless they are outside of the image in which case they are set to the Null block top-left is set to the top left block unless it is outside of the image in which case it is set to the left block if this block has no larger parent block or it is at the left side of its parent block and the top right block is not outside of the image then the top right block is used for top-right else the top-left block is used Null block y, cb, cr are 128 level, ref, mx and my are 0 Motion Vector Prediction:=========================1. the motion vectors of all the neighboring blocks are scaled to compensate for the difference of reference frames scaled_mv=(mv *(256 *(current_reference+1)/(mv.reference+1))+128)> the median of the scaled left
Definition: snow.txt:386
run_len
static const uint8_t run_len[7][16]
Definition: h264_cavlc.c:217
AV_RL32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:92
U
#define U(x)
Definition: vpx_arith.h:37
GLYPH_COORD_VECT_SIZE
#define GLYPH_COORD_VECT_SIZE
Definition: sanm.c:33
old_codec21
static int old_codec21(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int width, int height)
Definition: sanm.c:836
codec47_block
static int codec47_block(SANMVideoContext *ctx, GetByteContext *gb, uint8_t *dst, uint8_t *prev1, uint8_t *prev2, int stride, int size)
Definition: sanm.c:1403
AVCodecContext
main external API structure.
Definition: avcodec.h:431
c2
static const uint64_t c2
Definition: murmur3.c:53
SANMVideoContext::c47cb
uint8_t c47cb[4]
Definition: sanm.c:299
SANMVideoContext::rle_buf_size
unsigned int rle_buf_size
Definition: sanm.c:286
SANMVideoContext::buf_size
long buf_size
Definition: sanm.c:288
codec48_block
static int codec48_block(GetByteContext *gb, uint8_t *dst, uint8_t *db, int x, int y, const uint16_t w, const int aligned_height, const uint8_t *itbl)
Definition: sanm.c:1659
blt_ipol
static void blt_ipol(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int16_t left, int16_t top, uint16_t srcxoff, uint16_t srcyoff, uint16_t srcwidth, uint16_t srcheight, const uint16_t srcpitch, const uint16_t dstpitch, const uint16_t dstheight, int32_t size, const uint8_t *itbl)
Definition: sanm.c:1136
av_fast_padded_mallocz
void av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size)
Same behaviour av_fast_padded_malloc except that buffer will always be 0-initialized after call.
Definition: utils.c:66
which_direction
static enum GlyphDir which_direction(enum GlyphEdge edge0, enum GlyphEdge edge1)
Definition: sanm.c:341
SANMVideoContext::c4tbl
uint8_t c4tbl[2][256][16]
Definition: sanm.c:297
Windows::Graphics::DirectX::Direct3D11::p
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
Definition: vsrc_gfxcapture_winrt.hpp:53
codec4_load_tiles
static int codec4_load_tiles(SANMVideoContext *ctx, GetByteContext *gb, uint16_t param2, uint8_t clr)
Definition: sanm.c:597
av_clip_uint8
#define av_clip_uint8
Definition: common.h:106
RIGHT_EDGE
@ RIGHT_EDGE
Definition: sanm.c:305
AV_PICTURE_TYPE_P
@ AV_PICTURE_TYPE_P
Predicted.
Definition: avutil.h:279
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:200
SANMVideoContext::p8x8glyphs
int8_t p8x8glyphs[NGLYPHS][64]
Definition: sanm.c:294
mem.h
bytestream2_get_bufferu
static av_always_inline unsigned int bytestream2_get_bufferu(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:277
avpriv_request_sample
#define avpriv_request_sample(...)
Definition: tableprint_vlc.h:37
opcode_0xf7
static int opcode_0xf7(SANMVideoContext *ctx, int cx, int cy, int block_size, ptrdiff_t pitch)
Definition: sanm.c:2300
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AVPacket
This structure stores compressed data.
Definition: packet.h:535
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:458
codec33_gen_tiles
static void codec33_gen_tiles(SANMVideoContext *ctx, int8_t param1)
Definition: sanm.c:484
old_codec48
static int old_codec48(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int width, int height)
Definition: sanm.c:1838
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
av_fast_malloc
void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
Allocate a buffer, reusing the given one if large enough.
Definition: mem.c:557
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:592
int32_t
int32_t
Definition: audioconvert.c:56
bytestream.h
bytestream2_init
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
DIR_UP
@ DIR_UP
Definition: sanm.c:312
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
process_ftch
static int process_ftch(SANMVideoContext *ctx, int size)
Definition: sanm.c:2089
h
h
Definition: vp9dsp_template.c:2070
old_codec1
static int old_codec1(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int width, int height, int opaque)
Definition: sanm.c:881
SANMVideoContext::delta_pal
int16_t delta_pal[PALETTE_DELTA]
Definition: sanm.c:271
NO_DIR
@ NO_DIR
Definition: sanm.c:315
width
#define width
Definition: dsp.h:89
av_bswap16
#define av_bswap16
Definition: bswap.h:28
SANMVideoContext::pitch
ptrdiff_t pitch
Definition: sanm.c:273
skip
static void BS_FUNC() skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
Definition: bitstream_template.h:383
src
#define src
Definition: vp8dsp.c:248
SANMVideoContext::frm0_size
uint32_t frm0_size
Definition: sanm.c:281
SANMVideoContext::prev_seq
int prev_seq
Definition: sanm.c:276
SANMVideoContext::height
int height
Definition: sanm.c:274
decode_frame
static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *pkt)
Definition: sanm.c:2824
init_buffers
static av_cold int init_buffers(SANMVideoContext *ctx)
Definition: sanm.c:463