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 static const int8_t motion_vectors[256][2] = {
54  { 0, 0 }, { -1, -43 }, { 6, -43 }, { -9, -42 }, { 13, -41 },
55  { -16, -40 }, { 19, -39 }, { -23, -36 }, { 26, -34 }, { -2, -33 },
56  { 4, -33 }, { -29, -32 }, { -9, -32 }, { 11, -31 }, { -16, -29 },
57  { 32, -29 }, { 18, -28 }, { -34, -26 }, { -22, -25 }, { -1, -25 },
58  { 3, -25 }, { -7, -24 }, { 8, -24 }, { 24, -23 }, { 36, -23 },
59  { -12, -22 }, { 13, -21 }, { -38, -20 }, { 0, -20 }, { -27, -19 },
60  { -4, -19 }, { 4, -19 }, { -17, -18 }, { -8, -17 }, { 8, -17 },
61  { 18, -17 }, { 28, -17 }, { 39, -17 }, { -12, -15 }, { 12, -15 },
62  { -21, -14 }, { -1, -14 }, { 1, -14 }, { -41, -13 }, { -5, -13 },
63  { 5, -13 }, { 21, -13 }, { -31, -12 }, { -15, -11 }, { -8, -11 },
64  { 8, -11 }, { 15, -11 }, { -2, -10 }, { 1, -10 }, { 31, -10 },
65  { -23, -9 }, { -11, -9 }, { -5, -9 }, { 4, -9 }, { 11, -9 },
66  { 42, -9 }, { 6, -8 }, { 24, -8 }, { -18, -7 }, { -7, -7 },
67  { -3, -7 }, { -1, -7 }, { 2, -7 }, { 18, -7 }, { -43, -6 },
68  { -13, -6 }, { -4, -6 }, { 4, -6 }, { 8, -6 }, { -33, -5 },
69  { -9, -5 }, { -2, -5 }, { 0, -5 }, { 2, -5 }, { 5, -5 },
70  { 13, -5 }, { -25, -4 }, { -6, -4 }, { -3, -4 }, { 3, -4 },
71  { 9, -4 }, { -19, -3 }, { -7, -3 }, { -4, -3 }, { -2, -3 },
72  { -1, -3 }, { 0, -3 }, { 1, -3 }, { 2, -3 }, { 4, -3 },
73  { 6, -3 }, { 33, -3 }, { -14, -2 }, { -10, -2 }, { -5, -2 },
74  { -3, -2 }, { -2, -2 }, { -1, -2 }, { 0, -2 }, { 1, -2 },
75  { 2, -2 }, { 3, -2 }, { 5, -2 }, { 7, -2 }, { 14, -2 },
76  { 19, -2 }, { 25, -2 }, { 43, -2 }, { -7, -1 }, { -3, -1 },
77  { -2, -1 }, { -1, -1 }, { 0, -1 }, { 1, -1 }, { 2, -1 },
78  { 3, -1 }, { 10, -1 }, { -5, 0 }, { -3, 0 }, { -2, 0 },
79  { -1, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 }, { 5, 0 },
80  { 7, 0 }, { -10, 1 }, { -7, 1 }, { -3, 1 }, { -2, 1 },
81  { -1, 1 }, { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 },
82  { -43, 2 }, { -25, 2 }, { -19, 2 }, { -14, 2 }, { -5, 2 },
83  { -3, 2 }, { -2, 2 }, { -1, 2 }, { 0, 2 }, { 1, 2 },
84  { 2, 2 }, { 3, 2 }, { 5, 2 }, { 7, 2 }, { 10, 2 },
85  { 14, 2 }, { -33, 3 }, { -6, 3 }, { -4, 3 }, { -2, 3 },
86  { -1, 3 }, { 0, 3 }, { 1, 3 }, { 2, 3 }, { 4, 3 },
87  { 19, 3 }, { -9, 4 }, { -3, 4 }, { 3, 4 }, { 7, 4 },
88  { 25, 4 }, { -13, 5 }, { -5, 5 }, { -2, 5 }, { 0, 5 },
89  { 2, 5 }, { 5, 5 }, { 9, 5 }, { 33, 5 }, { -8, 6 },
90  { -4, 6 }, { 4, 6 }, { 13, 6 }, { 43, 6 }, { -18, 7 },
91  { -2, 7 }, { 0, 7 }, { 2, 7 }, { 7, 7 }, { 18, 7 },
92  { -24, 8 }, { -6, 8 }, { -42, 9 }, { -11, 9 }, { -4, 9 },
93  { 5, 9 }, { 11, 9 }, { 23, 9 }, { -31, 10 }, { -1, 10 },
94  { 2, 10 }, { -15, 11 }, { -8, 11 }, { 8, 11 }, { 15, 11 },
95  { 31, 12 }, { -21, 13 }, { -5, 13 }, { 5, 13 }, { 41, 13 },
96  { -1, 14 }, { 1, 14 }, { 21, 14 }, { -12, 15 }, { 12, 15 },
97  { -39, 17 }, { -28, 17 }, { -18, 17 }, { -8, 17 }, { 8, 17 },
98  { 17, 18 }, { -4, 19 }, { 0, 19 }, { 4, 19 }, { 27, 19 },
99  { 38, 20 }, { -13, 21 }, { 12, 22 }, { -36, 23 }, { -24, 23 },
100  { -8, 24 }, { 7, 24 }, { -3, 25 }, { 1, 25 }, { 22, 25 },
101  { 34, 26 }, { -18, 28 }, { -32, 29 }, { 16, 29 }, { -11, 31 },
102  { 9, 32 }, { 29, 32 }, { -4, 33 }, { 2, 33 }, { -26, 34 },
103  { 23, 36 }, { -19, 39 }, { 16, 40 }, { -13, 41 }, { 9, 42 },
104  { -6, 43 }, { 1, 43 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
105 };
106 
107 static const int8_t c37_mv[] = {
108  0, 0, 1, 0, 2, 0, 3, 0, 5, 0,
109  8, 0, 13, 0, 21, 0, -1, 0, -2, 0,
110  -3, 0, -5, 0, -8, 0, -13, 0, -17, 0,
111  -21, 0, 0, 1, 1, 1, 2, 1, 3, 1,
112  5, 1, 8, 1, 13, 1, 21, 1, -1, 1,
113  -2, 1, -3, 1, -5, 1, -8, 1, -13, 1,
114  -17, 1, -21, 1, 0, 2, 1, 2, 2, 2,
115  3, 2, 5, 2, 8, 2, 13, 2, 21, 2,
116  -1, 2, -2, 2, -3, 2, -5, 2, -8, 2,
117  -13, 2, -17, 2, -21, 2, 0, 3, 1, 3,
118  2, 3, 3, 3, 5, 3, 8, 3, 13, 3,
119  21, 3, -1, 3, -2, 3, -3, 3, -5, 3,
120  -8, 3, -13, 3, -17, 3, -21, 3, 0, 5,
121  1, 5, 2, 5, 3, 5, 5, 5, 8, 5,
122  13, 5, 21, 5, -1, 5, -2, 5, -3, 5,
123  -5, 5, -8, 5, -13, 5, -17, 5, -21, 5,
124  0, 8, 1, 8, 2, 8, 3, 8, 5, 8,
125  8, 8, 13, 8, 21, 8, -1, 8, -2, 8,
126  -3, 8, -5, 8, -8, 8, -13, 8, -17, 8,
127  -21, 8, 0, 13, 1, 13, 2, 13, 3, 13,
128  5, 13, 8, 13, 13, 13, 21, 13, -1, 13,
129  -2, 13, -3, 13, -5, 13, -8, 13, -13, 13,
130  -17, 13, -21, 13, 0, 21, 1, 21, 2, 21,
131  3, 21, 5, 21, 8, 21, 13, 21, 21, 21,
132  -1, 21, -2, 21, -3, 21, -5, 21, -8, 21,
133  -13, 21, -17, 21, -21, 21, 0, -1, 1, -1,
134  2, -1, 3, -1, 5, -1, 8, -1, 13, -1,
135  21, -1, -1, -1, -2, -1, -3, -1, -5, -1,
136  -8, -1, -13, -1, -17, -1, -21, -1, 0, -2,
137  1, -2, 2, -2, 3, -2, 5, -2, 8, -2,
138  13, -2, 21, -2, -1, -2, -2, -2, -3, -2,
139  -5, -2, -8, -2, -13, -2, -17, -2, -21, -2,
140  0, -3, 1, -3, 2, -3, 3, -3, 5, -3,
141  8, -3, 13, -3, 21, -3, -1, -3, -2, -3,
142  -3, -3, -5, -3, -8, -3, -13, -3, -17, -3,
143  -21, -3, 0, -5, 1, -5, 2, -5, 3, -5,
144  5, -5, 8, -5, 13, -5, 21, -5, -1, -5,
145  -2, -5, -3, -5, -5, -5, -8, -5, -13, -5,
146  -17, -5, -21, -5, 0, -8, 1, -8, 2, -8,
147  3, -8, 5, -8, 8, -8, 13, -8, 21, -8,
148  -1, -8, -2, -8, -3, -8, -5, -8, -8, -8,
149  -13, -8, -17, -8, -21, -8, 0, -13, 1, -13,
150  2, -13, 3, -13, 5, -13, 8, -13, 13, -13,
151  21, -13, -1, -13, -2, -13, -3, -13, -5, -13,
152  -8, -13, -13, -13, -17, -13, -21, -13, 0, -17,
153  1, -17, 2, -17, 3, -17, 5, -17, 8, -17,
154  13, -17, 21, -17, -1, -17, -2, -17, -3, -17,
155  -5, -17, -8, -17, -13, -17, -17, -17, -21, -17,
156  0, -21, 1, -21, 2, -21, 3, -21, 5, -21,
157  8, -21, 13, -21, 21, -21, -1, -21, -2, -21,
158  -3, -21, -5, -21, -8, -21, -13, -21, -17, -21,
159  0, 0, -8, -29, 8, -29, -18, -25, 17, -25,
160  0, -23, -6, -22, 6, -22, -13, -19, 12, -19,
161  0, -18, 25, -18, -25, -17, -5, -17, 5, -17,
162  -10, -15, 10, -15, 0, -14, -4, -13, 4, -13,
163  19, -13, -19, -12, -8, -11, -2, -11, 0, -11,
164  2, -11, 8, -11, -15, -10, -4, -10, 4, -10,
165  15, -10, -6, -9, -1, -9, 1, -9, 6, -9,
166  -29, -8, -11, -8, -8, -8, -3, -8, 3, -8,
167  8, -8, 11, -8, 29, -8, -5, -7, -2, -7,
168  0, -7, 2, -7, 5, -7, -22, -6, -9, -6,
169  -6, -6, -3, -6, -1, -6, 1, -6, 3, -6,
170  6, -6, 9, -6, 22, -6, -17, -5, -7, -5,
171  -4, -5, -2, -5, 0, -5, 2, -5, 4, -5,
172  7, -5, 17, -5, -13, -4, -10, -4, -5, -4,
173  -3, -4, -1, -4, 0, -4, 1, -4, 3, -4,
174  5, -4, 10, -4, 13, -4, -8, -3, -6, -3,
175  -4, -3, -3, -3, -2, -3, -1, -3, 0, -3,
176  1, -3, 2, -3, 4, -3, 6, -3, 8, -3,
177  -11, -2, -7, -2, -5, -2, -3, -2, -2, -2,
178  -1, -2, 0, -2, 1, -2, 2, -2, 3, -2,
179  5, -2, 7, -2, 11, -2, -9, -1, -6, -1,
180  -4, -1, -3, -1, -2, -1, -1, -1, 0, -1,
181  1, -1, 2, -1, 3, -1, 4, -1, 6, -1,
182  9, -1, -31, 0, -23, 0, -18, 0, -14, 0,
183  -11, 0, -7, 0, -5, 0, -4, 0, -3, 0,
184  -2, 0, -1, 0, 0, -31, 1, 0, 2, 0,
185  3, 0, 4, 0, 5, 0, 7, 0, 11, 0,
186  14, 0, 18, 0, 23, 0, 31, 0, -9, 1,
187  -6, 1, -4, 1, -3, 1, -2, 1, -1, 1,
188  0, 1, 1, 1, 2, 1, 3, 1, 4, 1,
189  6, 1, 9, 1, -11, 2, -7, 2, -5, 2,
190  -3, 2, -2, 2, -1, 2, 0, 2, 1, 2,
191  2, 2, 3, 2, 5, 2, 7, 2, 11, 2,
192  -8, 3, -6, 3, -4, 3, -2, 3, -1, 3,
193  0, 3, 1, 3, 2, 3, 3, 3, 4, 3,
194  6, 3, 8, 3, -13, 4, -10, 4, -5, 4,
195  -3, 4, -1, 4, 0, 4, 1, 4, 3, 4,
196  5, 4, 10, 4, 13, 4, -17, 5, -7, 5,
197  -4, 5, -2, 5, 0, 5, 2, 5, 4, 5,
198  7, 5, 17, 5, -22, 6, -9, 6, -6, 6,
199  -3, 6, -1, 6, 1, 6, 3, 6, 6, 6,
200  9, 6, 22, 6, -5, 7, -2, 7, 0, 7,
201  2, 7, 5, 7, -29, 8, -11, 8, -8, 8,
202  -3, 8, 3, 8, 8, 8, 11, 8, 29, 8,
203  -6, 9, -1, 9, 1, 9, 6, 9, -15, 10,
204  -4, 10, 4, 10, 15, 10, -8, 11, -2, 11,
205  0, 11, 2, 11, 8, 11, 19, 12, -19, 13,
206  -4, 13, 4, 13, 0, 14, -10, 15, 10, 15,
207  -5, 17, 5, 17, 25, 17, -25, 18, 0, 18,
208  -12, 19, 13, 19, -6, 22, 6, 22, 0, 23,
209  -17, 25, 18, 25, -8, 29, 8, 29, 0, 31,
210  0, 0, -6, -22, 6, -22, -13, -19, 12, -19,
211  0, -18, -5, -17, 5, -17, -10, -15, 10, -15,
212  0, -14, -4, -13, 4, -13, 19, -13, -19, -12,
213  -8, -11, -2, -11, 0, -11, 2, -11, 8, -11,
214  -15, -10, -4, -10, 4, -10, 15, -10, -6, -9,
215  -1, -9, 1, -9, 6, -9, -11, -8, -8, -8,
216  -3, -8, 0, -8, 3, -8, 8, -8, 11, -8,
217  -5, -7, -2, -7, 0, -7, 2, -7, 5, -7,
218  -22, -6, -9, -6, -6, -6, -3, -6, -1, -6,
219  1, -6, 3, -6, 6, -6, 9, -6, 22, -6,
220  -17, -5, -7, -5, -4, -5, -2, -5, -1, -5,
221  0, -5, 1, -5, 2, -5, 4, -5, 7, -5,
222  17, -5, -13, -4, -10, -4, -5, -4, -3, -4,
223  -2, -4, -1, -4, 0, -4, 1, -4, 2, -4,
224  3, -4, 5, -4, 10, -4, 13, -4, -8, -3,
225  -6, -3, -4, -3, -3, -3, -2, -3, -1, -3,
226  0, -3, 1, -3, 2, -3, 3, -3, 4, -3,
227  6, -3, 8, -3, -11, -2, -7, -2, -5, -2,
228  -4, -2, -3, -2, -2, -2, -1, -2, 0, -2,
229  1, -2, 2, -2, 3, -2, 4, -2, 5, -2,
230  7, -2, 11, -2, -9, -1, -6, -1, -5, -1,
231  -4, -1, -3, -1, -2, -1, -1, -1, 0, -1,
232  1, -1, 2, -1, 3, -1, 4, -1, 5, -1,
233  6, -1, 9, -1, -23, 0, -18, 0, -14, 0,
234  -11, 0, -7, 0, -5, 0, -4, 0, -3, 0,
235  -2, 0, -1, 0, 0, -23, 1, 0, 2, 0,
236  3, 0, 4, 0, 5, 0, 7, 0, 11, 0,
237  14, 0, 18, 0, 23, 0, -9, 1, -6, 1,
238  -5, 1, -4, 1, -3, 1, -2, 1, -1, 1,
239  0, 1, 1, 1, 2, 1, 3, 1, 4, 1,
240  5, 1, 6, 1, 9, 1, -11, 2, -7, 2,
241  -5, 2, -4, 2, -3, 2, -2, 2, -1, 2,
242  0, 2, 1, 2, 2, 2, 3, 2, 4, 2,
243  5, 2, 7, 2, 11, 2, -8, 3, -6, 3,
244  -4, 3, -3, 3, -2, 3, -1, 3, 0, 3,
245  1, 3, 2, 3, 3, 3, 4, 3, 6, 3,
246  8, 3, -13, 4, -10, 4, -5, 4, -3, 4,
247  -2, 4, -1, 4, 0, 4, 1, 4, 2, 4,
248  3, 4, 5, 4, 10, 4, 13, 4, -17, 5,
249  -7, 5, -4, 5, -2, 5, -1, 5, 0, 5,
250  1, 5, 2, 5, 4, 5, 7, 5, 17, 5,
251  -22, 6, -9, 6, -6, 6, -3, 6, -1, 6,
252  1, 6, 3, 6, 6, 6, 9, 6, 22, 6,
253  -5, 7, -2, 7, 0, 7, 2, 7, 5, 7,
254  -11, 8, -8, 8, -3, 8, 0, 8, 3, 8,
255  8, 8, 11, 8, -6, 9, -1, 9, 1, 9,
256  6, 9, -15, 10, -4, 10, 4, 10, 15, 10,
257  -8, 11, -2, 11, 0, 11, 2, 11, 8, 11,
258  19, 12, -19, 13, -4, 13, 4, 13, 0, 14,
259  -10, 15, 10, 15, -5, 17, 5, 17, 0, 18,
260  -12, 19, 13, 19, -6, 22, 6, 22, 0, 23,
261 };
262 
263 typedef struct SANMVideoContext {
266 
268  uint32_t pal[PALETTE_SIZE];
270 
271  ptrdiff_t pitch;
272  int width, height;
274  int prev_seq;
275 
277  uint16_t *fbuf, *frm0, *frm1, *frm2;
278  uint8_t *stored_frame;
281 
282  uint8_t *rle_buf;
283  unsigned int rle_buf_size;
284 
286 
288 
289  uint16_t codebook[256];
290  uint16_t small_codebook[4];
291 
292  int8_t p4x4glyphs[NGLYPHS][16];
293  int8_t p8x8glyphs[NGLYPHS][64];
294  uint8_t c47itbl[0x10000];
295  uint8_t c23lut[256];
296  uint8_t c4tbl[2][256][16];
297  uint16_t c4param;
299 
300 typedef struct SANMFrameHeader {
302 
303  uint16_t bg_color;
304  uint32_t width, height;
306 
307 enum GlyphEdge {
313 };
314 
315 enum GlyphDir {
321 };
322 
323 /**
324  * Return enum GlyphEdge of box where point (x, y) lies.
325  *
326  * @param x x point coordinate
327  * @param y y point coordinate
328  * @param edge_size box width/height.
329  */
330 static enum GlyphEdge which_edge(int x, int y, int edge_size)
331 {
332  const int edge_max = edge_size - 1;
333 
334  if (!y)
335  return BOTTOM_EDGE;
336  else if (y == edge_max)
337  return TOP_EDGE;
338  else if (!x)
339  return LEFT_EDGE;
340  else if (x == edge_max)
341  return RIGHT_EDGE;
342  else
343  return NO_EDGE;
344 }
345 
346 static enum GlyphDir which_direction(enum GlyphEdge edge0, enum GlyphEdge edge1)
347 {
348  if ((edge0 == LEFT_EDGE && edge1 == RIGHT_EDGE) ||
349  (edge1 == LEFT_EDGE && edge0 == RIGHT_EDGE) ||
350  (edge0 == BOTTOM_EDGE && edge1 != TOP_EDGE) ||
351  (edge1 == BOTTOM_EDGE && edge0 != TOP_EDGE))
352  return DIR_UP;
353  else if ((edge0 == TOP_EDGE && edge1 != BOTTOM_EDGE) ||
354  (edge1 == TOP_EDGE && edge0 != BOTTOM_EDGE))
355  return DIR_DOWN;
356  else if ((edge0 == LEFT_EDGE && edge1 != RIGHT_EDGE) ||
357  (edge1 == LEFT_EDGE && edge0 != RIGHT_EDGE))
358  return DIR_LEFT;
359  else if ((edge0 == TOP_EDGE && edge1 == BOTTOM_EDGE) ||
360  (edge1 == TOP_EDGE && edge0 == BOTTOM_EDGE) ||
361  (edge0 == RIGHT_EDGE && edge1 != LEFT_EDGE) ||
362  (edge1 == RIGHT_EDGE && edge0 != LEFT_EDGE))
363  return DIR_RIGHT;
364 
365  return NO_DIR;
366 }
367 
368 /* Interpolate two points. */
369 static void interp_point(int8_t *points, int x0, int y0, int x1, int y1,
370  int pos, int npoints)
371 {
372  if (npoints) {
373  points[0] = (x0 * pos + x1 * (npoints - pos) + (npoints >> 1)) / npoints;
374  points[1] = (y0 * pos + y1 * (npoints - pos) + (npoints >> 1)) / npoints;
375  } else {
376  points[0] = x0;
377  points[1] = y0;
378  }
379 }
380 
381 /**
382  * Construct glyphs by iterating through vector coordinates.
383  *
384  * @param pglyphs pointer to table where glyphs are stored
385  * @param xvec pointer to x component of vector coordinates
386  * @param yvec pointer to y component of vector coordinates
387  * @param side_length glyph width/height.
388  */
389 static void make_glyphs(int8_t *pglyphs, const int8_t *xvec, const int8_t *yvec,
390  const int side_length)
391 {
392  const int glyph_size = side_length * side_length;
393  int8_t *pglyph = pglyphs;
394 
395  int i, j;
396  for (i = 0; i < GLYPH_COORD_VECT_SIZE; i++) {
397  int x0 = xvec[i];
398  int y0 = yvec[i];
399  enum GlyphEdge edge0 = which_edge(x0, y0, side_length);
400 
401  for (j = 0; j < GLYPH_COORD_VECT_SIZE; j++, pglyph += glyph_size) {
402  int x1 = xvec[j];
403  int y1 = yvec[j];
404  enum GlyphEdge edge1 = which_edge(x1, y1, side_length);
405  enum GlyphDir dir = which_direction(edge0, edge1);
406  int npoints = FFMAX(FFABS(x1 - x0), FFABS(y1 - y0));
407  int ipoint;
408 
409  for (ipoint = 0; ipoint <= npoints; ipoint++) {
410  int8_t point[2];
411  int irow, icol;
412 
413  interp_point(point, x0, y0, x1, y1, ipoint, npoints);
414 
415  switch (dir) {
416  case DIR_UP:
417  for (irow = point[1]; irow >= 0; irow--)
418  pglyph[point[0] + irow * side_length] = 1;
419  break;
420 
421  case DIR_DOWN:
422  for (irow = point[1]; irow < side_length; irow++)
423  pglyph[point[0] + irow * side_length] = 1;
424  break;
425 
426  case DIR_LEFT:
427  for (icol = point[0]; icol >= 0; icol--)
428  pglyph[icol + point[1] * side_length] = 1;
429  break;
430 
431  case DIR_RIGHT:
432  for (icol = point[0]; icol < side_length; icol++)
433  pglyph[icol + point[1] * side_length] = 1;
434  break;
435  }
436  }
437  }
438  }
439 }
440 
441 static void init_sizes(SANMVideoContext *ctx, int width, int height)
442 {
443  ctx->width = width;
444  ctx->height = height;
445  ctx->npixels = width * height;
446 
447  ctx->aligned_width = FFALIGN(width, 8);
448  ctx->aligned_height = FFALIGN(height, 8);
449 
450  ctx->buf_size = ctx->aligned_width * ctx->aligned_height * sizeof(ctx->frm0[0]);
451  ctx->pitch = width;
452 }
453 
455 {
456  av_freep(&ctx->fbuf);
457  av_freep(&ctx->frm0);
458  av_freep(&ctx->frm1);
459  av_freep(&ctx->frm2);
460  av_freep(&ctx->stored_frame);
461  av_freep(&ctx->rle_buf);
462  ctx->frm0_size =
463  ctx->frm1_size =
464  ctx->frm2_size = 0;
465  init_sizes(ctx, 0, 0);
466 }
467 
469 {
470  av_fast_padded_mallocz(&ctx->fbuf, &ctx->fbuf_size, ctx->buf_size);
471  av_fast_padded_mallocz(&ctx->frm0, &ctx->frm0_size, ctx->buf_size);
472  av_fast_padded_mallocz(&ctx->frm1, &ctx->frm1_size, ctx->buf_size);
473  av_fast_padded_mallocz(&ctx->frm2, &ctx->frm2_size, ctx->buf_size);
474  if (!ctx->version)
475  av_fast_padded_mallocz(&ctx->stored_frame,
476  &ctx->stored_frame_size, ctx->buf_size);
477 
478  if (!ctx->frm0 || !ctx->frm1 || !ctx->frm2 ||
479  (!ctx->stored_frame && !ctx->version)) {
481  return AVERROR(ENOMEM);
482  }
483 
484  return 0;
485 }
486 
487 static void codec33_gen_tiles(SANMVideoContext *ctx, int8_t param1)
488 {
489  uint8_t *dst = &(ctx->c4tbl[0][0][0]);
490  int i, j, k, l, m, n, o, p;
491 
492  for (i = 0; i < 8; i++) {
493  for (k = 0; k < 8; k++) {
494  j = i + param1;
495  l = k + param1;
496  p = (j + l) >> 1;
497  n = (j + p) >> 1;
498  m = (p + l) >> 1;
499 
500  *dst++ = p; *dst++ = p; *dst++ = n; *dst++ = j;
501  *dst++ = p; *dst++ = p; *dst++ = n; *dst++ = j;
502  *dst++ = m; *dst++ = m; *dst++ = p; *dst++ = j;
503  *dst++ = l; *dst++ = l; *dst++ = m; *dst++ = p;
504  }
505  }
506 
507  for (i = 0; i < 8; i++) {
508  for (k = 0; k < 8; k++) {
509  j = i + param1;
510  l = k + param1;
511  n = (j + l) >> 1;
512  m = (l + n) >> 1;
513 
514  *dst++ = j; *dst++ = j; *dst++ = j; *dst++ = j;
515  *dst++ = n; *dst++ = n; *dst++ = n; *dst++ = n;
516  *dst++ = m; *dst++ = m; *dst++ = m; *dst++ = m;
517  *dst++ = l; *dst++ = l; *dst++ = l; *dst++ = l;
518  }
519  }
520 
521  for (i = 0; i < 8; i++) {
522  for (k = 0; k < 8; k++) {
523  j = i + param1;
524  l = k + param1;
525  m = (j + l) >> 1;
526  n = (j + m) >> 1;
527  o = (l + m) >> 1;
528 
529  *dst++ = j; *dst++ = j; *dst++ = n; *dst++ = m;
530  *dst++ = j; *dst++ = j; *dst++ = n; *dst++ = m;
531  *dst++ = n; *dst++ = n; *dst++ = m; *dst++ = o;
532  *dst++ = m; *dst++ = m; *dst++ = o; *dst++ = l;
533  }
534  }
535 
536  for (i = 0; i < 8; i++) {
537  for (k = 0; k < 8; k++) {
538  j = i + param1;
539  l = k + param1;
540  m = (j + l) >> 1;
541  n = (l + m) >> 1;
542 
543  *dst++ = j; *dst++ = m; *dst++ = n; *dst++ = l;
544  *dst++ = j; *dst++ = m; *dst++ = n; *dst++ = l;
545  *dst++ = j; *dst++ = m; *dst++ = n; *dst++ = l;
546  *dst++ = j; *dst++ = m; *dst++ = n; *dst++ = l;
547  }
548  }
549 }
550 
551 static void codec4_gen_tiles(SANMVideoContext *ctx, uint16_t param1)
552 {
553  uint8_t *dst = &(ctx->c4tbl[0][0][0]);
554  int i, j, k, l, m, n, o;
555 
556  for (i = 1; i < 16; i += 2) {
557  for (k = 0; k < 16; k++) {
558  j = i + param1;
559  l = k + param1;
560  m = (j + l) / 2;
561  n = (j + m) / 2;
562  o = (l + m) / 2;
563  if (j == m || l == m) {
564  *dst++ = l; *dst++ = j; *dst++ = l; *dst++ = j;
565  *dst++ = j; *dst++ = l; *dst++ = j; *dst++ = j;
566  *dst++ = l; *dst++ = j; *dst++ = l; *dst++ = j;
567  *dst++ = l; *dst++ = l; *dst++ = j; *dst++ = l;
568  } else {
569  *dst++ = m; *dst++ = m; *dst++ = n; *dst++ = j;
570  *dst++ = m; *dst++ = m; *dst++ = n; *dst++ = j;
571  *dst++ = o; *dst++ = o; *dst++ = m; *dst++ = n;
572  *dst++ = l; *dst++ = l; *dst++ = o; *dst++ = m;
573  }
574  }
575  }
576 
577  for (i = 0; i < 16; i += 2) {
578  for (k = 0; k < 16; k++) {
579  j = i + param1;
580  l = k + param1;
581  m = (j + l) / 2;
582  n = (j + m) / 2;
583  o = (l + m) / 2;
584  if (m == j || m == l) {
585  *dst++ = j; *dst++ = j; *dst++ = l; *dst++ = j;
586  *dst++ = j; *dst++ = j; *dst++ = j; *dst++ = l;
587  *dst++ = l; *dst++ = j; *dst++ = l; *dst++ = l;
588  *dst++ = j; *dst++ = l; *dst++ = j; *dst++ = l;
589  } else {
590  *dst++ = j; *dst++ = j; *dst++ = n; *dst++ = m;
591  *dst++ = j; *dst++ = j; *dst++ = n; *dst++ = m;
592  *dst++ = n; *dst++ = n; *dst++ = m; *dst++ = o;
593  *dst++ = m; *dst++ = m; *dst++ = o; *dst++ = l;
594  }
595  }
596  }
597 }
598 
599 
601  uint16_t param2, uint8_t clr)
602 {
603  uint8_t c, *dst = (uint8_t *)&(ctx->c4tbl[1][0][0]);
604  uint32_t loop = param2 * 8;
605 
606  if ((param2 > 256) || (bytestream2_get_bytes_left(gb) < loop))
607  return AVERROR_INVALIDDATA;
608 
609  while (loop--) {
610  c = bytestream2_get_byteu(gb);
611  *dst++ = (c >> 4) + clr;
612  *dst++ = (c & 0xf) + clr;
613  }
614 
615  return 0;
616 }
617 
618 static void rotate_bufs(SANMVideoContext *ctx, int rotate_code)
619 {
620  if (rotate_code == 2)
621  FFSWAP(uint16_t*, ctx->frm1, ctx->frm2);
622  FFSWAP(uint16_t*, ctx->frm2, ctx->frm0);
623 }
624 
626 {
627  SANMVideoContext *ctx = avctx->priv_data;
628 
629  ctx->avctx = avctx;
630  ctx->version = !avctx->extradata_size;
631  // early sanity check before allocations to avoid need for deallocation code.
632  if (!ctx->version && avctx->extradata_size < 1026) {
633  av_log(avctx, AV_LOG_ERROR, "Not enough extradata.\n");
634  return AVERROR_INVALIDDATA;
635  }
636 
637  avctx->pix_fmt = ctx->version ? AV_PIX_FMT_RGB565 : AV_PIX_FMT_PAL8;
638 
639  init_sizes(ctx, avctx->width, avctx->height);
640  if (init_buffers(ctx)) {
641  av_log(avctx, AV_LOG_ERROR, "Error allocating buffers.\n");
642  return AVERROR(ENOMEM);
643  }
644 
645  make_glyphs(ctx->p4x4glyphs[0], glyph4_x, glyph4_y, 4);
646  make_glyphs(ctx->p8x8glyphs[0], glyph8_x, glyph8_y, 8);
647 
648  if (!ctx->version) {
649  int i;
650 
651  ctx->subversion = AV_RL16(avctx->extradata);
652  for (i = 0; i < PALETTE_SIZE; i++)
653  ctx->pal[i] = 0xFFU << 24 | AV_RL32(avctx->extradata + 2 + i * 4);
654  if (ctx->subversion < 2)
655  ctx->pal[0] = 0xFFU << 24;
656  }
657  ctx->c4param = 0xffff;
658 
659  return 0;
660 }
661 
663 {
664  SANMVideoContext *ctx = avctx->priv_data;
665 
667 
668  return 0;
669 }
670 
671 static int old_codec4(SANMVideoContext *ctx, GetByteContext *gb, int top, int left,
672  int w, int h, uint8_t param, uint16_t param2, int codec)
673 {
674  const uint16_t p = ctx->pitch;
675  const uint32_t maxpxo = ctx->height * p;
676  uint8_t mask, bits, idx, *gs, *dst = (uint8_t *)ctx->fbuf;
677  int i, j, k, l, bit, ret;
678  int32_t pxoff, pxo2;
679 
680  if (ctx->c4param != param) {
681  if (codec > 32)
682  codec33_gen_tiles(ctx, param);
683  else
684  codec4_gen_tiles(ctx, param);
685  ctx->c4param = param;
686  }
687  if (param2 > 0) {
688  ret = codec4_load_tiles(ctx, gb, param2, param);
689  if (ret)
690  return ret;
691  }
692 
693  if (codec > 32)
694  codec -= 29;
695 
696  for (j = 0; j < w; j += 4) {
697  mask = bits = 0;
698  for (i = 0; i < h; i += 4) {
699  pxoff = j + left + ((top + i) * p);
700  if (param2 > 0) {
701  if (bits == 0) {
702  if (bytestream2_get_bytes_left(gb) < 1)
703  return AVERROR_INVALIDDATA;
704  mask = bytestream2_get_byteu(gb);
705  bits = 8;
706  }
707  bit = !!(mask & 0x80);
708  mask <<= 1;
709  bits--;
710  } else {
711  bit = 0;
712  }
713 
714  if (bytestream2_get_bytes_left(gb) < 1)
715  return AVERROR_INVALIDDATA;
716  idx = bytestream2_get_byteu(gb);
717  if ((bit == 0) && (idx == 0x80) && (codec != 5))
718  continue;
719 
720  gs = &(ctx->c4tbl[bit][idx][0]);
721  pxo2 = pxoff;
722  for (k = 0; k < 4; k++) {
723  for (l = 0; l < 4; l++) {
724  if (pxo2 >= 0 && pxo2 < maxpxo) {
725  *(dst + pxo2) = *gs;
726  }
727  gs++;
728  pxo2++;
729  }
730  pxo2 = pxo2 - 4 + p;
731  }
732  }
733  }
734  return 0;
735 }
736 
737 static int rle_decode(SANMVideoContext *ctx, GetByteContext *gb, uint8_t *dst, const int out_size)
738 {
739  int opcode, color, run_len, left = out_size;
740 
741  while (left > 0) {
742  opcode = bytestream2_get_byte(gb);
743  run_len = (opcode >> 1) + 1;
744  if (run_len > left || bytestream2_get_bytes_left(gb) <= 0)
745  return AVERROR_INVALIDDATA;
746 
747  if (opcode & 1) {
748  color = bytestream2_get_byte(gb);
749  memset(dst, color, run_len);
750  } else {
752  return AVERROR_INVALIDDATA;
754  }
755 
756  dst += run_len;
757  left -= run_len;
758  }
759 
760  return 0;
761 }
762 
763 static int old_codec23(SANMVideoContext *ctx, GetByteContext *gb, int top, int left,
764  int width, int height, uint8_t param, uint16_t param2)
765 {
766  const uint32_t maxpxo = ctx->height * ctx->pitch;
767  uint8_t *dst, lut[256], c;
768  int i, j, k, pc, sk;
769  int32_t pxoff;
770 
771  if (ctx->subversion < 2) {
772  /* Rebel Assault 1: constant offset + 0xd0 */
773  for (i = 0; i < 256; i++)
774  lut[i] = (i + param + 0xd0) & 0xff;
775  } else if (param2 == 256) {
776  if (bytestream2_get_bytes_left(gb) < 256)
777  return AVERROR_INVALIDDATA;
778  bytestream2_get_bufferu(gb, ctx->c23lut, 256);
779  } else if (param2 < 256) {
780  for (i = 0; i < 256; i++)
781  lut[i] = (i + param2) & 0xff;
782  } else {
783  memcpy(lut, ctx->c23lut, 256);
784  }
785  if (bytestream2_get_bytes_left(gb) < 1)
786  return 0; /* some c23 frames just set up the LUT */
787 
788  dst = (uint8_t *)ctx->fbuf;
789  for (i = 0; i < height; i++) {
790  if (bytestream2_get_bytes_left(gb) < 2)
791  return 0;
792  pxoff = left + ((top + i) * ctx->pitch);
793  k = bytestream2_get_le16u(gb);
794  sk = 1;
795  pc = 0;
796  while (k > 0 && pc <= width) {
797  if (bytestream2_get_bytes_left(gb) < 1)
798  return AVERROR_INVALIDDATA;
799  j = bytestream2_get_byteu(gb);
800  if (sk) {
801  pxoff += j;
802  pc += j;
803  } else {
804  while (j--) {
805  if (pxoff >=0 && pxoff < maxpxo) {
806  c = *(dst + pxoff);
807  *(dst + pxoff) = lut[c];
808  }
809  pxoff++;
810  pc++;
811  }
812  }
813  sk ^= 1;
814  }
815  }
816  return 0;
817 }
818 
819 static int old_codec21(SANMVideoContext *ctx, GetByteContext *gb, int top, int left,
820  int width, int height)
821 {
822  const uint32_t maxpxo = ctx->height * ctx->pitch;
823  uint8_t *dst = (uint8_t *)ctx->fbuf, c;
824  int i, j, k, pc, sk, pxoff;
825 
826  dst = (uint8_t *)ctx->fbuf;
827  for (i = 0; i < height; i++) {
828  if (bytestream2_get_bytes_left(gb) < 2)
829  return 0;
830  pxoff = left + ((top + i) * ctx->pitch);
831  k = bytestream2_get_le16u(gb);
832  sk = 1;
833  pc = 0;
834  while (k > 0 && pc <= width) {
835  if (bytestream2_get_bytes_left(gb) < 2)
836  return AVERROR_INVALIDDATA;
837  j = bytestream2_get_le16u(gb);
838  k -= 2;
839  if (sk) {
840  pxoff += j;
841  pc += j;
842  } else {
843  if (bytestream2_get_bytes_left(gb) < (j + 1))
844  return AVERROR_INVALIDDATA;
845  do {
846  c = bytestream2_get_byteu(gb);
847  if (pxoff >=0 && pxoff < maxpxo) {
848  *(dst + pxoff) = c;
849  }
850  pxoff++;
851  pc++;
852  j--;
853  k--;
854  } while (j > -1);
855  }
856  sk ^= 1;
857  }
858  }
859  return 0;
860 }
861 
862 static int old_codec1(SANMVideoContext *ctx, GetByteContext *gb, int top,
863  int left, int width, int height, int opaque)
864 {
865  int i, j, len, flag, code, val, end, pxoff;
866  const int maxpxo = ctx->height * ctx->pitch;
867  uint8_t *dst = (uint8_t *)ctx->fbuf;
868 
869  for (i = 0; i < height; i++) {
870  if (bytestream2_get_bytes_left(gb) < 2)
871  return AVERROR_INVALIDDATA;
872 
873  len = bytestream2_get_le16u(gb);
874  end = bytestream2_tell(gb) + len;
875 
876  pxoff = left + ((top + i) * ctx->pitch);
877  while (bytestream2_tell(gb) < end) {
878  if (bytestream2_get_bytes_left(gb) < 2)
879  return AVERROR_INVALIDDATA;
880 
881  code = bytestream2_get_byteu(gb);
882  flag = code & 1;
883  code = (code >> 1) + 1;
884  if (flag) {
885  val = bytestream2_get_byteu(gb);
886  if (val || opaque) {
887  for (j = 0; j < code; j++) {
888  if (pxoff >= 0 && pxoff < maxpxo)
889  *(dst + pxoff) = val;
890  pxoff++;
891  }
892  } else {
893  pxoff += code;
894  }
895  } else {
897  return AVERROR_INVALIDDATA;
898  for (j = 0; j < code; j++) {
899  val = bytestream2_get_byteu(gb);
900  if ((pxoff >= 0) && (pxoff < maxpxo) && (val || opaque))
901  *(dst + pxoff) = val;
902  pxoff++;
903  }
904  }
905  }
906  }
907  ctx->rotate_code = 0;
908 
909  return 0;
910 }
911 
912 static int old_codec31(SANMVideoContext *ctx, GetByteContext *gb, int top,
913  int left, int width, int height, int p1, int opaque)
914 {
915  int i, j, len, flag, code, val, end, pxoff;
916  const int maxpxo = ctx->height * ctx->pitch;
917  uint8_t *dst = (uint8_t *)ctx->fbuf;
918 
919  for (i = 0; i < height; i++) {
920  if (bytestream2_get_bytes_left(gb) < 2)
921  return AVERROR_INVALIDDATA;
922 
923  len = bytestream2_get_le16u(gb);
924  end = bytestream2_tell(gb) + len;
925 
926  pxoff = left + ((top + i) * ctx->pitch);
927  while (bytestream2_tell(gb) < end) {
928  if (bytestream2_get_bytes_left(gb) < 2)
929  return AVERROR_INVALIDDATA;
930 
931  code = bytestream2_get_byteu(gb);
932  flag = code & 1;
933  code = (code >> 1) + 1;
934  if (flag) {
935  val = bytestream2_get_byteu(gb);
936  for (j = 0; j < code; j++) {
937  if ((0 != (val & 0xf)) || opaque) {
938  if (pxoff >= 0 && pxoff < maxpxo)
939  *(dst + pxoff) = p1 + (val & 0xf);
940  }
941  pxoff++;
942  if ((0 != (val >> 4)) || opaque) {
943  if (pxoff >= 0 && pxoff < maxpxo)
944  *(dst + pxoff) = p1 + (val >> 4);
945  }
946  pxoff++;
947  }
948  } else {
950  return AVERROR_INVALIDDATA;
951  for (j = 0; j < code; j++) {
952  val = bytestream2_get_byteu(gb);
953  if ((pxoff >= 0) && (pxoff < maxpxo) && ((0 != (val & 0xf)) || opaque))
954  *(dst + pxoff) = p1 + (val & 0xf);
955  pxoff++;
956  if ((pxoff >= 0) && (pxoff < maxpxo) && ((0 != (val >> 4)) || opaque))
957  *(dst + pxoff) = p1 + (val >> 4);
958  pxoff++;
959  }
960  }
961  }
962  }
963  ctx->rotate_code = 0;
964 
965  return 0;
966 }
967 
968 static int old_codec2(SANMVideoContext *ctx, GetByteContext *gb, int top,
969  int left, int width, int height)
970 {
971  uint8_t *dst = (uint8_t *)ctx->fbuf, col;
972  int16_t xpos = left, ypos = top;
973 
974  while (bytestream2_get_bytes_left(gb) > 3) {
975  xpos += bytestream2_get_le16u(gb);
976  ypos += bytestream2_get_byteu(gb);
977  col = bytestream2_get_byteu(gb);
978  if (xpos >= 0 && ypos >= 0 &&
979  xpos < ctx->width && ypos < ctx->height) {
980  *(dst + xpos + ypos * ctx->pitch) = col;
981  }
982  }
983  return 0;
984 }
985 
986 static int old_codec20(SANMVideoContext *ctx, int w, int h)
987 {
988  uint8_t *dst = (uint8_t *)ctx->fbuf;
989 
990  if (bytestream2_get_bytes_left(&ctx->gb) < w * h)
991  return AVERROR_INVALIDDATA;
992 
993  if (w == ctx->pitch) {
994  bytestream2_get_bufferu(&ctx->gb, dst, w * h);
995  } else {
996  for (int i = 0; i < h; i++) {
998  dst += ctx->pitch;
999  }
1000  }
1001  return 0;
1002 }
1003 
1004 static inline void codec37_mv(uint8_t *dst, const uint8_t *src,
1005  int height, int stride, int x, int y)
1006 {
1007  int pos, i, j;
1008 
1009  pos = x + y * stride;
1010  for (j = 0; j < 4; j++) {
1011  for (i = 0; i < 4; i++) {
1012  if ((pos + i) < 0 || (pos + i) >= height * stride)
1013  dst[i] = 0;
1014  else
1015  dst[i] = src[i];
1016  }
1017  dst += stride;
1018  src += stride;
1019  pos += stride;
1020  }
1021 }
1022 
1024 {
1025  int i, j, k, l, t, run, len, code, skip, mx, my;
1026  ptrdiff_t stride = ctx->pitch;
1027  uint8_t *dst, *prev;
1028  int skip_run = 0;
1029  int compr = bytestream2_get_byte(&ctx->gb);
1030  int mvoff = bytestream2_get_byte(&ctx->gb);
1031  int seq = bytestream2_get_le16(&ctx->gb);
1032  uint32_t decoded_size = bytestream2_get_le32(&ctx->gb);
1033  int flags;
1034 
1035  bytestream2_skip(&ctx->gb, 4);
1036  flags = bytestream2_get_byte(&ctx->gb);
1037  bytestream2_skip(&ctx->gb, 3);
1038 
1039  if (decoded_size > ctx->height * stride) {
1040  decoded_size = ctx->height * stride;
1041  av_log(ctx->avctx, AV_LOG_WARNING, "Decoded size is too large.\n");
1042  }
1043 
1044  ctx->rotate_code = 0;
1045 
1046  if (((seq & 1) || !(flags & 1)) && (compr && compr != 2)) {
1047  FFSWAP(uint16_t*, ctx->frm0, ctx->frm2);
1048  }
1049 
1050  dst = ((uint8_t*)ctx->frm0);
1051  prev = ((uint8_t*)ctx->frm2);
1052 
1053  if (mvoff > 2) {
1054  av_log(ctx->avctx, AV_LOG_ERROR, "Invalid motion base value %d.\n", mvoff);
1055  return AVERROR_INVALIDDATA;
1056  }
1057 
1058  switch (compr) {
1059  case 0:
1060  for (i = 0; i < height; i++) {
1062  dst += stride;
1063  }
1064  memset(ctx->frm2, 0, ctx->height * stride);
1065  break;
1066  case 1:
1067  run = 0;
1068  len = -1;
1069  code = 0;
1070 
1071  for (j = 0; j < height; j += 4) {
1072  for (i = 0; i < width; i += 4) {
1073  if (len < 0) {
1074  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1075  return AVERROR_INVALIDDATA;
1076  code = bytestream2_get_byte(&ctx->gb);
1077  len = code >> 1;
1078  run = code & 1;
1079  skip = 0;
1080  } else {
1081  skip = run;
1082  }
1083 
1084  if (!skip) {
1085  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1086  return AVERROR_INVALIDDATA;
1087  code = bytestream2_get_byte(&ctx->gb);
1088  if (code == 0xff) {
1089  len--;
1090  for (k = 0; k < 4; k++) {
1091  for (l = 0; l < 4; l++) {
1092  if (len < 0) {
1093  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1094  return AVERROR_INVALIDDATA;
1095  code = bytestream2_get_byte(&ctx->gb);
1096  len = code >> 1;
1097  run = code & 1;
1098  if (run) {
1099  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1100  return AVERROR_INVALIDDATA;
1101  code = bytestream2_get_byte(&ctx->gb);
1102  }
1103  }
1104  if (!run) {
1105  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1106  return AVERROR_INVALIDDATA;
1107  code = bytestream2_get_byte(&ctx->gb);
1108  }
1109  *(dst + i + (k * stride) + l) = code;
1110  len--;
1111  }
1112  }
1113  continue;
1114  }
1115  }
1116  /* 4x4 block copy from prev with MV */
1117  mx = c37_mv[(mvoff * 255 + code) * 2];
1118  my = c37_mv[(mvoff * 255 + code) * 2 + 1];
1119  codec37_mv(dst + i, prev + i + mx + my * stride,
1120  ctx->height, stride, i + mx, j + my);
1121  len--;
1122  }
1123  dst += stride * 4;
1124  prev += stride * 4;
1125  }
1126  break;
1127  case 2:
1128  if (rle_decode(ctx, &ctx->gb, dst, decoded_size))
1129  return AVERROR_INVALIDDATA;
1130  memset(ctx->frm2, 0, ctx->frm2_size);
1131  break;
1132  case 3:
1133  case 4:
1134  for (j = 0; j < height; j += 4) {
1135  for (i = 0; i < width; i += 4) {
1136  int code;
1137  if (skip_run) {
1138  skip_run--;
1139  copy_block4(dst + i, prev + i, stride, stride, 4);
1140  continue;
1141  }
1142  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1143  return AVERROR_INVALIDDATA;
1144  code = bytestream2_get_byteu(&ctx->gb);
1145  if (code == 0xFF) {
1146  if (bytestream2_get_bytes_left(&ctx->gb) < 16)
1147  return AVERROR_INVALIDDATA;
1148  for (k = 0; k < 4; k++)
1149  bytestream2_get_bufferu(&ctx->gb, dst + i + k * stride, 4);
1150  } else if ((flags & 4) && (code == 0xFE)) {
1151  if (bytestream2_get_bytes_left(&ctx->gb) < 4)
1152  return AVERROR_INVALIDDATA;
1153  for (k = 0; k < 4; k++)
1154  memset(dst + i + k * stride, bytestream2_get_byteu(&ctx->gb), 4);
1155  } else if ((flags & 4) && (code == 0xFD)) {
1156  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1157  return AVERROR_INVALIDDATA;
1158  t = bytestream2_get_byteu(&ctx->gb);
1159  for (k = 0; k < 4; k++)
1160  memset(dst + i + k * stride, t, 4);
1161  } else {
1162  mx = c37_mv[(mvoff * 255 + code) * 2];
1163  my = c37_mv[(mvoff * 255 + code) * 2 + 1];
1164  codec37_mv(dst + i, prev + i + mx + my * stride,
1165  ctx->height, stride, i + mx, j + my);
1166 
1167  if ((compr == 4) && (code == 0)) {
1168  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1169  return AVERROR_INVALIDDATA;
1170  skip_run = bytestream2_get_byteu(&ctx->gb);
1171  }
1172  }
1173  }
1174  dst += stride * 4;
1175  prev += stride * 4;
1176  }
1177  break;
1178  default:
1180  "Subcodec 37 compression %d", compr);
1181  return AVERROR_PATCHWELCOME;
1182  }
1183 
1184  return 0;
1185 }
1186 
1187 static int process_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *prev1,
1188  uint8_t *prev2, int stride, int tbl, int size)
1189 {
1190  int code, k, t;
1191  uint8_t colors[2];
1192  int8_t *pglyph;
1193 
1194  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1195  return AVERROR_INVALIDDATA;
1196 
1197  code = bytestream2_get_byteu(&ctx->gb);
1198  if (code >= 0xF8) {
1199  switch (code) {
1200  case 0xFF:
1201  if (size == 2) {
1202  if (bytestream2_get_bytes_left(&ctx->gb) < 4)
1203  return AVERROR_INVALIDDATA;
1204  dst[0] = bytestream2_get_byteu(&ctx->gb);
1205  dst[1] = bytestream2_get_byteu(&ctx->gb);
1206  dst[0 + stride] = bytestream2_get_byteu(&ctx->gb);
1207  dst[1 + stride] = bytestream2_get_byteu(&ctx->gb);
1208  } else {
1209  size >>= 1;
1210  if (process_block(ctx, dst, prev1, prev2, stride, tbl, size))
1211  return AVERROR_INVALIDDATA;
1212  if (process_block(ctx, dst + size, prev1 + size, prev2 + size,
1213  stride, tbl, size))
1214  return AVERROR_INVALIDDATA;
1215  dst += size * stride;
1216  prev1 += size * stride;
1217  prev2 += size * stride;
1218  if (process_block(ctx, dst, prev1, prev2, stride, tbl, size))
1219  return AVERROR_INVALIDDATA;
1220  if (process_block(ctx, dst + size, prev1 + size, prev2 + size,
1221  stride, tbl, size))
1222  return AVERROR_INVALIDDATA;
1223  }
1224  break;
1225  case 0xFE:
1226  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1227  return AVERROR_INVALIDDATA;
1228 
1229  t = bytestream2_get_byteu(&ctx->gb);
1230  for (k = 0; k < size; k++)
1231  memset(dst + k * stride, t, size);
1232  break;
1233  case 0xFD:
1234  if (bytestream2_get_bytes_left(&ctx->gb) < 3)
1235  return AVERROR_INVALIDDATA;
1236 
1237  code = bytestream2_get_byteu(&ctx->gb);
1238  pglyph = (size == 8) ? ctx->p8x8glyphs[code] : ctx->p4x4glyphs[code];
1239  bytestream2_get_bufferu(&ctx->gb, colors, 2);
1240 
1241  for (k = 0; k < size; k++)
1242  for (t = 0; t < size; t++)
1243  dst[t + k * stride] = colors[!*pglyph++];
1244  break;
1245  case 0xFC:
1246  for (k = 0; k < size; k++)
1247  memcpy(dst + k * stride, prev1 + k * stride, size);
1248  break;
1249  default:
1250  k = bytestream2_tell(&ctx->gb);
1251  bytestream2_seek(&ctx->gb, tbl + (code & 7), SEEK_SET);
1252  t = bytestream2_get_byte(&ctx->gb);
1253  bytestream2_seek(&ctx->gb, k, SEEK_SET);
1254  for (k = 0; k < size; k++)
1255  memset(dst + k * stride, t, size);
1256  }
1257  } else {
1258  int mx = motion_vectors[code][0];
1259  int my = motion_vectors[code][1];
1260  int index = prev2 - (const uint8_t *)ctx->frm2;
1261 
1262  av_assert2(index >= 0 && index < (ctx->buf_size >> 1));
1263 
1264  if (index < -mx - my * stride ||
1265  (ctx->buf_size >> 1) - index < mx + size + (my + size - 1) * stride) {
1266  av_log(ctx->avctx, AV_LOG_ERROR, "MV is invalid.\n");
1267  return AVERROR_INVALIDDATA;
1268  }
1269 
1270  for (k = 0; k < size; k++)
1271  memcpy(dst + k * stride, prev2 + mx + (my + k) * stride, size);
1272  }
1273 
1274  return 0;
1275 }
1276 
1278 {
1279  uint8_t *p1, *p2, *itbl = ctx->c47itbl;
1280  int i, j;
1281 
1282  for (i = 0; i < 256; i++) {
1283  p1 = p2 = itbl + i;
1284  for (j = 256 - i; j; j--) {
1285  *p1 = *p2 = bytestream2_get_byte(&ctx->gb);
1286  p1 += 1;
1287  p2 += 256;
1288  }
1289  itbl += 256;
1290  }
1291 }
1292 
1293 static void codec47_comp1(SANMVideoContext *ctx, uint8_t *dst_in, int width,
1294  int height, ptrdiff_t stride)
1295 {
1296  uint8_t p1, *dst, *itbl = ctx->c47itbl;
1297  uint16_t px;
1298  int i, j;
1299 
1300  dst = dst_in + stride;
1301  for (i = 0; i < height; i += 2) {
1302  p1 = bytestream2_get_byte(&ctx->gb);
1303  *dst++ = p1;
1304  *dst++ = p1;
1305  px = p1;
1306  for (j = 2; j < width; j += 2) {
1307  p1 = bytestream2_get_byte(&ctx->gb);
1308  px = (px << 8) | p1;
1309  *dst++ = itbl[px];
1310  *dst++ = p1;
1311  }
1312  dst += stride;
1313  }
1314 
1315  memcpy(dst_in, dst_in + stride, width);
1316  dst = dst_in + stride + stride;
1317  for (i = 2; i < height - 1; i += 2) {
1318  for (j = 0; j < width; j++) {
1319  px = (*(dst - stride) << 8) | *(dst + stride);
1320  *dst++ = itbl[px];
1321  }
1322  dst += stride;
1323  }
1324 }
1325 
1327 {
1328  uint32_t decoded_size;
1329  int i, j;
1330  ptrdiff_t stride = ctx->pitch;
1331  uint8_t *dst = (uint8_t *)ctx->frm0;
1332  uint8_t *prev1 = (uint8_t *)ctx->frm1;
1333  uint8_t *prev2 = (uint8_t *)ctx->frm2;
1334  uint8_t auxcol[2];
1335  int tbl_pos = bytestream2_tell(&ctx->gb);
1336  int seq = bytestream2_get_le16(&ctx->gb);
1337  int compr = bytestream2_get_byte(&ctx->gb);
1338  int new_rot = bytestream2_get_byte(&ctx->gb);
1339  int skip = bytestream2_get_byte(&ctx->gb);
1340 
1341  bytestream2_skip(&ctx->gb, 7);
1342  auxcol[0] = bytestream2_get_byteu(&ctx->gb);
1343  auxcol[1] = bytestream2_get_byteu(&ctx->gb);
1344  decoded_size = bytestream2_get_le32(&ctx->gb);
1345  bytestream2_skip(&ctx->gb, 8);
1346 
1347  if (decoded_size > ctx->height * stride) {
1348  decoded_size = ctx->height * stride;
1349  av_log(ctx->avctx, AV_LOG_WARNING, "Decoded size is too large.\n");
1350  }
1351 
1352  if (skip & 1) {
1353  if (bytestream2_get_bytes_left(&ctx->gb) < 0x8080)
1354  return AVERROR_INVALIDDATA;
1356  }
1357  if (!seq) {
1358  ctx->prev_seq = -1;
1359  memset(prev1, auxcol[0], ctx->height * stride);
1360  memset(prev2, auxcol[1], ctx->height * stride);
1361  }
1362 
1363  switch (compr) {
1364  case 0:
1366  return AVERROR_INVALIDDATA;
1367  for (j = 0; j < height; j++) {
1369  dst += stride;
1370  }
1371  break;
1372  case 1:
1373  if (bytestream2_get_bytes_left(&ctx->gb) < ((width + 1) >> 1) * ((height + 1) >> 1))
1374  return AVERROR_INVALIDDATA;
1376  break;
1377  case 2:
1378  if (seq == ctx->prev_seq + 1) {
1379  for (j = 0; j < height; j += 8) {
1380  for (i = 0; i < width; i += 8)
1381  if (process_block(ctx, dst + i, prev1 + i, prev2 + i, stride,
1382  tbl_pos + 8, 8))
1383  return AVERROR_INVALIDDATA;
1384  dst += stride * 8;
1385  prev1 += stride * 8;
1386  prev2 += stride * 8;
1387  }
1388  }
1389  break;
1390  case 3:
1391  memcpy(ctx->frm0, ctx->frm2, ctx->pitch * ctx->height);
1392  break;
1393  case 4:
1394  memcpy(ctx->frm0, ctx->frm1, ctx->pitch * ctx->height);
1395  break;
1396  case 5:
1397  if (rle_decode(ctx, &ctx->gb, dst, decoded_size))
1398  return AVERROR_INVALIDDATA;
1399  break;
1400  default:
1402  "Subcodec 47 compression %d", compr);
1403  return AVERROR_PATCHWELCOME;
1404  }
1405  if (seq == ctx->prev_seq + 1)
1406  ctx->rotate_code = new_rot;
1407  else
1408  ctx->rotate_code = 0;
1409  ctx->prev_seq = seq;
1410 
1411  return 0;
1412 }
1413 
1414 // scale 4x4 input block to an 8x8 output block
1415 static void c48_4to8(uint8_t *dst, const uint8_t *src, const uint16_t w)
1416 {
1417  uint16_t p;
1418  // dst is always at least 16bit aligned
1419  for (int i = 0; i < 4; i++) {
1420  for (int j = 0; j < 8; j += 2) {
1421  p = *src++;
1422  p = (p << 8) | p;
1423  *((uint16_t *)(dst + w * 0 + j)) = p;
1424  *((uint16_t *)(dst + w * 1 + j)) = p;
1425  }
1426  dst += w * 2;
1427  }
1428 }
1429 
1430 static int codec48_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *db,
1431  const uint16_t w)
1432 {
1433  uint8_t opc, sb[16];
1434  int i, j, k, l;
1435  int16_t mvofs;
1436  uint32_t ofs;
1437 
1438  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1439  return 1;
1440 
1441  opc = bytestream2_get_byteu(&ctx->gb);
1442  switch (opc) {
1443  case 0xFF: // 1x1 -> 8x8 block scale
1444  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1445  return 1;
1446 
1447  opc = bytestream2_get_byteu(&ctx->gb);
1448  for (i = 0; i < 16; i++)
1449  sb[i] = opc;
1450  c48_4to8(dst, sb, w);
1451  break;
1452  case 0xFE: // 1x 8x8 copy from deltabuf, 16bit mv from source
1453  if (bytestream2_get_bytes_left(&ctx->gb) < 2)
1454  return 1;
1455  mvofs = bytestream2_get_le16(&ctx->gb);
1456  for (i = 0; i < 8; i++) {
1457  ofs = w * i;
1458  for (k = 0; k < 8; k++)
1459  *(dst + ofs + k) = *(db + ofs + k + mvofs);
1460  }
1461  break;
1462  case 0xFD: // 2x2 -> 8x8 block scale
1463  if (bytestream2_get_bytes_left(&ctx->gb) < 4)
1464  return 1;
1465  sb[ 5] = bytestream2_get_byteu(&ctx->gb);
1466  sb[ 7] = bytestream2_get_byteu(&ctx->gb);
1467  sb[13] = bytestream2_get_byteu(&ctx->gb);
1468  sb[15] = bytestream2_get_byteu(&ctx->gb);
1469 
1470  sb[0] = sb[1] = sb[4] = sb[5];
1471  sb[2] = sb[3] = sb[6] = sb[7];
1472  sb[8] = sb[9] = sb[12] = sb[13];
1473  sb[10] = sb[11] = sb[14] = sb[15];
1474  c48_4to8(dst, sb, w);
1475  break;
1476  case 0xFC: // 4x copy 4x4 block, per-block c37_mv from source
1477  if (bytestream2_get_bytes_left(&ctx->gb) < 4)
1478  return 1;
1479  for (i = 0; i < 8; i += 4) {
1480  for (k = 0; k < 8; k += 4) {
1481  opc = bytestream2_get_byteu(&ctx->gb);
1482  mvofs = c37_mv[opc * 2] + (c37_mv[opc * 2 + 1] * w);
1483  for (j = 0; j < 4; j++) {
1484  ofs = (w * (j + i)) + k;
1485  for (l = 0; l < 4; l++)
1486  *(dst + ofs + l) = *(db + ofs + l + mvofs);
1487  }
1488  }
1489  }
1490  break;
1491  case 0xFB: // Copy 4x 4x4 blocks, per-block mv from source
1492  if (bytestream2_get_bytes_left(&ctx->gb) < 8)
1493  return 1;
1494  for (i = 0; i < 8; i += 4) {
1495  for (k = 0; k < 8; k += 4) {
1496  mvofs = bytestream2_get_le16(&ctx->gb);
1497  for (j = 0; j < 4; j++) {
1498  ofs = (w * (j + i)) + k;
1499  for (l = 0; l < 4; l++)
1500  *(dst + ofs + l) = *(db + ofs + l + mvofs);
1501  }
1502  }
1503  }
1504  break;
1505  case 0xFA: // scale 4x4 input block to 8x8 dest block
1506  if (bytestream2_get_bytes_left(&ctx->gb) < 16)
1507  return 1;
1508  bytestream2_get_bufferu(&ctx->gb, sb, 16);
1509  c48_4to8(dst, sb, w);
1510  break;
1511  case 0xF9: // 16x 2x2 copy from delta, per-block c37_mv from source
1512  if (bytestream2_get_bytes_left(&ctx->gb) < 16)
1513  return 1;
1514  for (i = 0; i < 8; i += 2) {
1515  for (j = 0; j < 8; j += 2) {
1516  ofs = (w * i) + j;
1517  opc = bytestream2_get_byteu(&ctx->gb);
1518  mvofs = c37_mv[opc * 2] + (c37_mv[opc * 2 + 1] * w);
1519  for (l = 0; l < 2; l++) {
1520  *(dst + ofs + l + 0) = *(db + ofs + l + 0 + mvofs);
1521  *(dst + ofs + l + w) = *(db + ofs + l + w + mvofs);
1522  }
1523  }
1524  }
1525  break;
1526  case 0xF8: // 16x 2x2 blocks copy, 16bit mv from source
1527  if (bytestream2_get_bytes_left(&ctx->gb) < 32)
1528  return 1;
1529  for (i = 0; i < 8; i += 2) {
1530  for (j = 0; j < 8; j += 2) {
1531  ofs = w * i + j;
1532  mvofs = bytestream2_get_le16(&ctx->gb);
1533  for (l = 0; l < 2; l++) {
1534  *(dst + ofs + l + 0) = *(db + ofs + l + 0 + mvofs);
1535  *(dst + ofs + l + w) = *(db + ofs + l + w + mvofs);
1536  }
1537  }
1538  }
1539  break;
1540  case 0xF7: // copy 8x8 block from src to dest
1541  if (bytestream2_get_bytes_left(&ctx->gb) < 64)
1542  return 1;
1543  for (i = 0; i < 8; i++) {
1544  ofs = i * w;
1545  for (l = 0; l < 8; l++)
1546  *(dst + ofs + l) = bytestream2_get_byteu(&ctx->gb);
1547  }
1548  break;
1549  default: // copy 8x8 block from prev, c37_mv from source
1550  mvofs = c37_mv[opc * 2] + (c37_mv[opc * 2 + 1] * w);
1551  for (i = 0; i < 8; i++) {
1552  ofs = i * w;
1553  for (l = 0; l < 8; l++)
1554  *(dst + ofs + l) = *(db + ofs + l + mvofs);
1555  }
1556  break;
1557  }
1558  return 0;
1559 }
1560 
1562 {
1563  uint8_t *dst, *prev;
1564  int compr = bytestream2_get_byte(&ctx->gb);
1565  int mvidx = bytestream2_get_byte(&ctx->gb);
1566  int seq = bytestream2_get_le16(&ctx->gb);
1567  uint32_t decoded_size = bytestream2_get_le32(&ctx->gb);
1568  int i, j, flags;
1569 
1570  // all codec48 videos use 1, but just to be safe...
1571  if (mvidx != 1) {
1572  av_log(ctx->avctx, AV_LOG_ERROR, "Invalid motion base value %d.\n", mvidx);
1573  return AVERROR_INVALIDDATA;
1574  }
1575 
1576  bytestream2_skip(&ctx->gb, 4);
1577  flags = bytestream2_get_byte(&ctx->gb);
1578  bytestream2_skip(&ctx->gb, 3);
1579 
1580  if (flags & 8) {
1581  if (bytestream2_get_bytes_left(&ctx->gb) < 0x8080)
1582  return AVERROR_INVALIDDATA;
1584  }
1585 
1586  dst = (uint8_t*)ctx->frm0;
1587  prev = (uint8_t*)ctx->frm2;
1588 
1589  if (!seq) {
1590  ctx->prev_seq = -1;
1591  memset(prev, 0, ctx->aligned_height * width);
1592  }
1593 
1594  switch (compr) {
1595  case 0:
1597  return AVERROR_INVALIDDATA;
1598  for (j = 0; j < height; j++) {
1600  dst += width;
1601  }
1602  break;
1603  case 2:
1604  if (decoded_size > ctx->buf_size) {
1605  av_log(ctx->avctx, AV_LOG_ERROR, "Decoded size %u is too large.\n", decoded_size);
1606  return AVERROR_INVALIDDATA;
1607  }
1608 
1609  if (rle_decode(ctx, &ctx->gb, dst, decoded_size))
1610  return AVERROR_INVALIDDATA;
1611  break;
1612  case 3:
1613  if (seq == ctx->prev_seq + 1) {
1614  for (j = 0; j < height; j += 8) {
1615  for (i = 0; i < width; i += 8) {
1616  if (codec48_block(ctx, dst + i, prev + i, width))
1617  return AVERROR_INVALIDDATA;
1618  }
1619  dst += width * 8;
1620  prev += width * 8;
1621  }
1622  }
1623  break;
1624  case 5:
1625  if (bytestream2_get_bytes_left(&ctx->gb) < ((width + 1) >> 1) * ((height + 1) >> 1))
1626  return AVERROR_INVALIDDATA;
1628  break;
1629  case 6: // in some videos of "Star Wars - Making Magic", ignored.
1630  break;
1631  default:
1633  "Subcodec 48 compression %d", compr);
1634  return AVERROR_PATCHWELCOME;
1635  }
1636  ctx->rotate_code = 1; // swap frm[0] and frm[2]
1637  ctx->prev_seq = seq;
1638  return 0;
1639 }
1640 
1642 {
1643  uint16_t w, h, parm2;
1644  uint8_t codec, param;
1645  int16_t left, top;
1646  int fsc, sote, ret;
1647 
1648  codec = bytestream2_get_byteu(gb);
1649  param = bytestream2_get_byteu(gb);
1650  left = bytestream2_get_le16u(gb);
1651  top = bytestream2_get_le16u(gb);
1652  w = bytestream2_get_le16u(gb);
1653  h = bytestream2_get_le16u(gb);
1654  bytestream2_skip(gb, 2);
1655  parm2 = bytestream2_get_le16u(gb);
1656 
1657  if (w < 1 || h < 1 || w > 800 || h > 600 || left > 800 || top > 600 || left + w <= 0 || top + h <= 0) {
1658  av_log(ctx->avctx, AV_LOG_WARNING,
1659  "ignoring invalid fobj dimensions: c%d %d %d @ %d %d\n",
1660  codec, w, h, left, top);
1661  return 0;
1662  }
1663 
1664  /* codecs with their own buffers */
1665  fsc = (codec == 37 || codec == 47 || codec == 48);
1666 
1667  /* special case for "Shadows of the Empire" videos */
1668  sote = ((w == 640) && (h == 272) && (codec == 47));
1669  if (sote)
1670  left = top = 0;
1671 
1672  if (!ctx->have_dimensions) {
1673  int xres, yres;
1674  if (ctx->subversion < 2) {
1675  /* Rebel Assault 1: 384x242 internal size */
1676  xres = 384;
1677  yres = 242;
1678  if (w > xres || h > yres)
1679  return AVERROR_INVALIDDATA;
1680  ctx->have_dimensions = 1;
1681  } else if (codec == 37 || codec == 47 || codec == 48) {
1682  /* these codecs work on full frames, trust their dimensions */
1683  xres = w;
1684  yres = h;
1685  ctx->have_dimensions = 1;
1686  } else {
1687  /* detect common sizes */
1688  xres = w + left;
1689  yres = h + top;
1690  if (sote) {
1691  /* SotE: has top=60 at all times to center video
1692  * inside the 640x480 game window
1693  */
1694  xres = w;
1695  yres = h;
1696  ctx->have_dimensions = 1;
1697  } else if (((xres == 424) && (yres == 260)) || /* RA1 */
1698  ((xres == 320) && (yres == 200)) || /* ft/dig/... */
1699  ((xres == 640) && (yres == 480))) { /* ol/comi/mots... */
1700  ctx->have_dimensions = 1;
1701  }
1702 
1703  xres = FFMAX(xres, ctx->width);
1704  yres = FFMAX(yres, ctx->height);
1705  }
1706 
1707  if (ctx->width < xres || ctx->height < yres) {
1708  int ret = ff_set_dimensions(ctx->avctx, xres, yres);
1709  if (ret < 0)
1710  return ret;
1711  init_sizes(ctx, xres, yres);
1712  if (init_buffers(ctx)) {
1713  av_log(ctx->avctx, AV_LOG_ERROR, "Error resizing buffers.\n");
1714  return AVERROR(ENOMEM);
1715  }
1716  }
1717  } else {
1718  if (((left + w > ctx->width) || (top + h > ctx->height)) && (fsc || codec == 20)) {
1719  /* correct unexpected overly large frames: this happens
1720  * for instance with The Dig's sq1.san video: it has a few
1721  * (all black) 640x480 frames halfway in, while the rest is
1722  * 320x200.
1723  */
1724  av_log(ctx->avctx, AV_LOG_WARNING,
1725  "resizing too large fobj: c%d %d %d @ %d %d\n", codec, w, h, left, top);
1726  w = ctx->width;
1727  h = ctx->height;
1728  }
1729  }
1730 
1731  /* clear the main buffer on the first fob */
1732  if (ctx->first_fob) {
1733  ctx->first_fob = 0;
1734  if (!fsc)
1735  memset(ctx->fbuf, 0, ctx->frm0_size);
1736  }
1737 
1738  switch (codec) {
1739  case 1:
1740  case 3:
1741  return old_codec1(ctx, gb, top, left, w, h, codec == 3);
1742  case 2:
1743  return old_codec2(ctx, gb, top, left, w, h);
1744  case 4:
1745  case 5:
1746  case 33:
1747  case 34:
1748  return old_codec4(ctx, gb, top, left, w, h, param, parm2, codec);
1749  case 20:
1750  return old_codec20(ctx, w, h);
1751  case 21:
1752  return old_codec21(ctx, gb, top, left, w, h);
1753  case 23:
1754  return old_codec23(ctx, gb, top, left, w, h, param, parm2);
1755  case 31:
1756  case 32:
1757  return old_codec31(ctx, gb, top, left, w, h, param, (codec == 32));
1758  case 37:
1759  ret = old_codec37(ctx, w, h); break;
1760  case 45:
1761  return 0;
1762  case 47:
1763  ret = old_codec47(ctx, w, h); break;
1764  case 48:
1765  ret = old_codec48(ctx, w, h); break;
1766  default:
1767  avpriv_request_sample(ctx->avctx, "Subcodec %d", codec);
1768  ctx->frame->flags |= AV_FRAME_FLAG_CORRUPT;
1769  return 0;
1770  }
1771  if (ret)
1772  return ret;
1773 
1774  /* copy the codec37/47/48 result to main buffer */
1775  if ((w == ctx->width) && (h == ctx->height)) {
1776  memcpy(ctx->fbuf, ctx->frm0, ctx->fbuf_size);
1777  } else {
1778  const uint8_t *src = (uint8_t *)ctx->frm0;
1779  const int cw = FFMIN(w, ctx->width - left);
1780  const int ch = FFMIN(h, ctx->height - top);
1781  if ((cw > 0) && (ch > 0) && (left >= 0) && (top >= 0)) {
1782  uint8_t *dst = (uint8_t *)ctx->fbuf + left + top * ctx->pitch;
1783  for (int i = 0; i < ch; i++) {
1784  memcpy(dst, src, cw);
1785  dst += ctx->pitch;
1786  src += w;
1787  }
1788  }
1789  }
1790  return 0;
1791 }
1792 
1794 {
1795  uint8_t *sf = ctx->stored_frame;
1796  int xoff, yoff, left, top, ret;
1797  GetByteContext gb;
1798  uint32_t sz;
1799 
1800  /* FTCH defines additional x/y offsets */
1801  if (size != 12) {
1802  if (bytestream2_get_bytes_left(&ctx->gb) < 6)
1803  return AVERROR_INVALIDDATA;
1804  bytestream2_skip(&ctx->gb, 2);
1805  xoff = bytestream2_get_le16u(&ctx->gb);
1806  yoff = bytestream2_get_le16u(&ctx->gb);
1807  } else {
1808  if (bytestream2_get_bytes_left(&ctx->gb) < 12)
1809  return AVERROR_INVALIDDATA;
1810  bytestream2_skip(&ctx->gb, 4);
1811  xoff = bytestream2_get_be32u(&ctx->gb);
1812  yoff = bytestream2_get_be32u(&ctx->gb);
1813  }
1814 
1815  sz = *(uint32_t *)(sf + 0);
1816  if ((sz > 0) && (sz <= ctx->stored_frame_size - 4)) {
1817  /* add the FTCH offsets to the left/top values of the stored FOBJ */
1818  left = av_le2ne16(*(int16_t *)(sf + 4 + 2));
1819  top = av_le2ne16(*(int16_t *)(sf + 4 + 4));
1820  *(int16_t *)(sf + 4 + 2) = av_le2ne16(left + xoff);
1821  *(int16_t *)(sf + 4 + 4) = av_le2ne16(top + yoff);
1822 
1823  /* decode the stored FOBJ */
1824  bytestream2_init(&gb, sf + 4, sz);
1825  ret = process_frame_obj(ctx, &gb);
1826 
1827  /* now restore the original left/top values again */
1828  *(int16_t *)(sf + 4 + 2) = av_le2ne16(left);
1829  *(int16_t *)(sf + 4 + 4) = av_le2ne16(top);
1830  } else {
1831  /* this happens a lot in RA1: The individual files are meant to
1832  * be played in sequence, with some referencing objects STORed
1833  * by previous files, e.g. the cockpit codec21 object in RA1 LVL8.
1834  * But spamming the log with errors is also not helpful, so
1835  * here we simply ignore this case.
1836  */
1837  ret = 0;
1838  }
1839  return ret;
1840 }
1841 
1843 {
1844  int16_t *dp = ctx->delta_pal;
1845  uint32_t *pal = ctx->pal;
1846  uint16_t cmd;
1847  uint8_t c[3];
1848  int i, j;
1849 
1850  bytestream2_skip(&ctx->gb, 2);
1851  cmd = bytestream2_get_be16(&ctx->gb);
1852 
1853  if (cmd == 1) {
1854  for (i = 0; i < PALETTE_DELTA; i += 3) {
1855  c[0] = (*pal >> 16) & 0xFF;
1856  c[1] = (*pal >> 8) & 0xFF;
1857  c[2] = (*pal >> 0) & 0xFF;
1858  for (j = 0; j < 3; j++) {
1859  int cl = (c[j] * 129) + *dp++;
1860  c[j] = av_clip_uint8(cl / 128) & 0xFF;
1861  }
1862  *pal++ = 0xFFU << 24 | c[0] << 16 | c[1] << 8 | c[2];
1863  }
1864  } else if (cmd == 2) {
1865  if (size < PALETTE_DELTA * 2 + 4) {
1866  av_log(ctx->avctx, AV_LOG_ERROR,
1867  "Incorrect palette change block size %"PRIu32".\n", size);
1868  return AVERROR_INVALIDDATA;
1869  }
1870  for (i = 0; i < PALETTE_DELTA; i++)
1871  dp[i] = bytestream2_get_le16u(&ctx->gb);
1872 
1873  if (size >= PALETTE_DELTA * 2 + 4 + PALETTE_SIZE * 3) {
1874  for (i = 0; i < PALETTE_SIZE; i++)
1875  ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb);
1876  if (ctx->subversion < 2)
1877  ctx->pal[0] = 0xFFU << 24;
1878  }
1879  }
1880  return 0;
1881 }
1882 
1884 {
1885  uint16_t *frm = ctx->frm0;
1886  int x, y;
1887 
1888  if (bytestream2_get_bytes_left(&ctx->gb) < ctx->width * ctx->height * 2) {
1889  av_log(ctx->avctx, AV_LOG_ERROR, "Insufficient data for raw frame.\n");
1890  return AVERROR_INVALIDDATA;
1891  }
1892  for (y = 0; y < ctx->height; y++) {
1893  for (x = 0; x < ctx->width; x++)
1894  frm[x] = bytestream2_get_le16u(&ctx->gb);
1895  frm += ctx->pitch;
1896  }
1897  return 0;
1898 }
1899 
1901 {
1902  avpriv_request_sample(ctx->avctx, "Unknown/unsupported compression type");
1903  return AVERROR_PATCHWELCOME;
1904 }
1905 
1906 static void copy_block(uint16_t *pdest, uint16_t *psrc, int block_size, ptrdiff_t pitch)
1907 {
1908  uint8_t *dst = (uint8_t *)pdest;
1909  uint8_t *src = (uint8_t *)psrc;
1910  ptrdiff_t stride = pitch * 2;
1911 
1912  switch (block_size) {
1913  case 2:
1914  copy_block4(dst, src, stride, stride, 2);
1915  break;
1916  case 4:
1917  copy_block8(dst, src, stride, stride, 4);
1918  break;
1919  case 8:
1920  copy_block16(dst, src, stride, stride, 8);
1921  break;
1922  }
1923 }
1924 
1925 static void fill_block(uint16_t *pdest, uint16_t color, int block_size, ptrdiff_t pitch)
1926 {
1927  int x, y;
1928 
1929  pitch -= block_size;
1930  for (y = 0; y < block_size; y++, pdest += pitch)
1931  for (x = 0; x < block_size; x++)
1932  *pdest++ = color;
1933 }
1934 
1935 static int draw_glyph(SANMVideoContext *ctx, uint16_t *dst, int index,
1936  uint16_t fg_color, uint16_t bg_color, int block_size,
1937  ptrdiff_t pitch)
1938 {
1939  int8_t *pglyph;
1940  uint16_t colors[2] = { fg_color, bg_color };
1941  int x, y;
1942 
1943  if (index >= NGLYPHS) {
1944  av_log(ctx->avctx, AV_LOG_ERROR, "Ignoring nonexistent glyph #%u.\n", index);
1945  return AVERROR_INVALIDDATA;
1946  }
1947 
1948  pglyph = block_size == 8 ? ctx->p8x8glyphs[index] : ctx->p4x4glyphs[index];
1949  pitch -= block_size;
1950 
1951  for (y = 0; y < block_size; y++, dst += pitch)
1952  for (x = 0; x < block_size; x++)
1953  *dst++ = colors[*pglyph++];
1954  return 0;
1955 }
1956 
1957 static int opcode_0xf7(SANMVideoContext *ctx, int cx, int cy, int block_size, ptrdiff_t pitch)
1958 {
1959  uint16_t *dst = ctx->frm0 + cx + cy * ctx->pitch;
1960 
1961  if (block_size == 2) {
1962  uint32_t indices;
1963 
1964  if (bytestream2_get_bytes_left(&ctx->gb) < 4)
1965  return AVERROR_INVALIDDATA;
1966 
1967  indices = bytestream2_get_le32u(&ctx->gb);
1968  dst[0] = ctx->codebook[indices & 0xFF];
1969  indices >>= 8;
1970  dst[1] = ctx->codebook[indices & 0xFF];
1971  indices >>= 8;
1972  dst[pitch] = ctx->codebook[indices & 0xFF];
1973  indices >>= 8;
1974  dst[pitch + 1] = ctx->codebook[indices & 0xFF];
1975  } else {
1976  uint16_t fgcolor, bgcolor;
1977  int glyph;
1978 
1979  if (bytestream2_get_bytes_left(&ctx->gb) < 3)
1980  return AVERROR_INVALIDDATA;
1981 
1982  glyph = bytestream2_get_byteu(&ctx->gb);
1983  bgcolor = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
1984  fgcolor = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
1985 
1986  draw_glyph(ctx, dst, glyph, fgcolor, bgcolor, block_size, pitch);
1987  }
1988  return 0;
1989 }
1990 
1991 static int opcode_0xf8(SANMVideoContext *ctx, int cx, int cy, int block_size, ptrdiff_t pitch)
1992 {
1993  uint16_t *dst = ctx->frm0 + cx + cy * ctx->pitch;
1994 
1995  if (block_size == 2) {
1996  if (bytestream2_get_bytes_left(&ctx->gb) < 8)
1997  return AVERROR_INVALIDDATA;
1998 
1999  dst[0] = bytestream2_get_le16u(&ctx->gb);
2000  dst[1] = bytestream2_get_le16u(&ctx->gb);
2001  dst[pitch] = bytestream2_get_le16u(&ctx->gb);
2002  dst[pitch + 1] = bytestream2_get_le16u(&ctx->gb);
2003  } else {
2004  uint16_t fgcolor, bgcolor;
2005  int glyph;
2006 
2007  if (bytestream2_get_bytes_left(&ctx->gb) < 5)
2008  return AVERROR_INVALIDDATA;
2009 
2010  glyph = bytestream2_get_byteu(&ctx->gb);
2011  bgcolor = bytestream2_get_le16u(&ctx->gb);
2012  fgcolor = bytestream2_get_le16u(&ctx->gb);
2013 
2014  draw_glyph(ctx, dst, glyph, fgcolor, bgcolor, block_size, pitch);
2015  }
2016  return 0;
2017 }
2018 
2019 static int good_mvec(SANMVideoContext *ctx, int cx, int cy, int mx, int my,
2020  int block_size)
2021 {
2022  int start_pos = cx + mx + (cy + my) * ctx->pitch;
2023  int end_pos = start_pos + (block_size - 1) * (ctx->pitch + 1);
2024 
2025  int good = start_pos >= 0 && end_pos < (ctx->buf_size >> 1);
2026 
2027  if (!good)
2028  av_log(ctx->avctx, AV_LOG_ERROR,
2029  "Ignoring invalid motion vector (%i, %i)->(%u, %u), block size = %u\n",
2030  cx + mx, cy + my, cx, cy, block_size);
2031 
2032  return good;
2033 }
2034 
2035 static int codec2subblock(SANMVideoContext *ctx, int cx, int cy, int blk_size)
2036 {
2037  int16_t mx, my, index;
2038  int opcode;
2039 
2040  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
2041  return AVERROR_INVALIDDATA;
2042 
2043  opcode = bytestream2_get_byteu(&ctx->gb);
2044 
2045  switch (opcode) {
2046  default:
2047  mx = motion_vectors[opcode][0];
2048  my = motion_vectors[opcode][1];
2049 
2050  if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
2051  copy_block(ctx->frm0 + cx + ctx->pitch * cy,
2052  ctx->frm2 + cx + mx + ctx->pitch * (cy + my),
2053  blk_size, ctx->pitch);
2054  }
2055  break;
2056  case 0xF5:
2057  if (bytestream2_get_bytes_left(&ctx->gb) < 2)
2058  return AVERROR_INVALIDDATA;
2059  index = bytestream2_get_le16u(&ctx->gb);
2060 
2061  mx = index % ctx->width;
2062  my = index / ctx->width;
2063 
2064  if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
2065  copy_block(ctx->frm0 + cx + ctx->pitch * cy,
2066  ctx->frm2 + cx + mx + ctx->pitch * (cy + my),
2067  blk_size, ctx->pitch);
2068  }
2069  break;
2070  case 0xF6:
2071  copy_block(ctx->frm0 + cx + ctx->pitch * cy,
2072  ctx->frm1 + cx + ctx->pitch * cy,
2073  blk_size, ctx->pitch);
2074  break;
2075  case 0xF7:
2076  opcode_0xf7(ctx, cx, cy, blk_size, ctx->pitch);
2077  break;
2078 
2079  case 0xF8:
2080  opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch);
2081  break;
2082  case 0xF9:
2083  case 0xFA:
2084  case 0xFB:
2085  case 0xFC:
2086  fill_block(ctx->frm0 + cx + cy * ctx->pitch,
2087  ctx->small_codebook[opcode - 0xf9], blk_size, ctx->pitch);
2088  break;
2089  case 0xFD:
2090  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
2091  return AVERROR_INVALIDDATA;
2092  fill_block(ctx->frm0 + cx + cy * ctx->pitch,
2093  ctx->codebook[bytestream2_get_byteu(&ctx->gb)], blk_size, ctx->pitch);
2094  break;
2095  case 0xFE:
2096  if (bytestream2_get_bytes_left(&ctx->gb) < 2)
2097  return AVERROR_INVALIDDATA;
2098  fill_block(ctx->frm0 + cx + cy * ctx->pitch,
2099  bytestream2_get_le16u(&ctx->gb), blk_size, ctx->pitch);
2100  break;
2101  case 0xFF:
2102  if (blk_size == 2) {
2103  opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch);
2104  } else {
2105  blk_size >>= 1;
2106  if (codec2subblock(ctx, cx, cy, blk_size))
2107  return AVERROR_INVALIDDATA;
2108  if (codec2subblock(ctx, cx + blk_size, cy, blk_size))
2109  return AVERROR_INVALIDDATA;
2110  if (codec2subblock(ctx, cx, cy + blk_size, blk_size))
2111  return AVERROR_INVALIDDATA;
2112  if (codec2subblock(ctx, cx + blk_size, cy + blk_size, blk_size))
2113  return AVERROR_INVALIDDATA;
2114  }
2115  break;
2116  }
2117  return 0;
2118 }
2119 
2121 {
2122  int cx, cy, ret;
2123 
2124  for (cy = 0; cy < ctx->aligned_height; cy += 8)
2125  for (cx = 0; cx < ctx->aligned_width; cx += 8)
2126  if (ret = codec2subblock(ctx, cx, cy, 8))
2127  return ret;
2128 
2129  return 0;
2130 }
2131 
2133 {
2134  memcpy(ctx->frm0, ctx->frm2, ctx->frm2_size);
2135  return 0;
2136 }
2137 
2139 {
2140  memcpy(ctx->frm0, ctx->frm1, ctx->frm1_size);
2141  return 0;
2142 }
2143 
2145 {
2146 #if HAVE_BIGENDIAN
2147  uint16_t *frm;
2148  int npixels;
2149 #endif
2150  uint8_t *dst = (uint8_t*)ctx->frm0;
2151 
2152  if (rle_decode(ctx, &ctx->gb, dst, ctx->buf_size))
2153  return AVERROR_INVALIDDATA;
2154 
2155 #if HAVE_BIGENDIAN
2156  npixels = ctx->npixels;
2157  frm = ctx->frm0;
2158  while (npixels--) {
2159  *frm = av_bswap16(*frm);
2160  frm++;
2161  }
2162 #endif
2163 
2164  return 0;
2165 }
2166 
2168 {
2169  int npixels = ctx->npixels;
2170  uint16_t *frm = ctx->frm0;
2171 
2172  if (bytestream2_get_bytes_left(&ctx->gb) < npixels) {
2173  av_log(ctx->avctx, AV_LOG_ERROR, "Insufficient data for frame.\n");
2174  return AVERROR_INVALIDDATA;
2175  }
2176  while (npixels--)
2177  *frm++ = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
2178 
2179  return 0;
2180 }
2181 
2183 {
2184  uint16_t *pdest = ctx->frm0;
2185  uint8_t *rsrc;
2186  long npixels = ctx->npixels;
2187 
2188  av_fast_malloc(&ctx->rle_buf, &ctx->rle_buf_size, npixels);
2189  if (!ctx->rle_buf) {
2190  av_log(ctx->avctx, AV_LOG_ERROR, "RLE buffer allocation failed.\n");
2191  return AVERROR(ENOMEM);
2192  }
2193  rsrc = ctx->rle_buf;
2194 
2195  if (rle_decode(ctx, &ctx->gb, rsrc, npixels))
2196  return AVERROR_INVALIDDATA;
2197 
2198  while (npixels--)
2199  *pdest++ = ctx->codebook[*rsrc++];
2200 
2201  return 0;
2202 }
2203 
2205 
2206 static const frm_decoder v1_decoders[] = {
2209 };
2210 
2212 {
2213  int i, ret;
2214 
2215  if ((ret = bytestream2_get_bytes_left(&ctx->gb)) < 560) {
2216  av_log(ctx->avctx, AV_LOG_ERROR, "Input frame too short (%d bytes).\n",
2217  ret);
2218  return AVERROR_INVALIDDATA;
2219  }
2220  bytestream2_skip(&ctx->gb, 8); // skip pad
2221 
2222  hdr->width = bytestream2_get_le32u(&ctx->gb);
2223  hdr->height = bytestream2_get_le32u(&ctx->gb);
2224 
2225  if (hdr->width != ctx->width || hdr->height != ctx->height) {
2226  avpriv_report_missing_feature(ctx->avctx, "Variable size frames");
2227  return AVERROR_PATCHWELCOME;
2228  }
2229 
2230  hdr->seq_num = bytestream2_get_le16u(&ctx->gb);
2231  hdr->codec = bytestream2_get_byteu(&ctx->gb);
2232  hdr->rotate_code = bytestream2_get_byteu(&ctx->gb);
2233 
2234  bytestream2_skip(&ctx->gb, 4); // skip pad
2235 
2236  for (i = 0; i < 4; i++)
2237  ctx->small_codebook[i] = bytestream2_get_le16u(&ctx->gb);
2238  hdr->bg_color = bytestream2_get_le16u(&ctx->gb);
2239 
2240  bytestream2_skip(&ctx->gb, 2); // skip pad
2241 
2242  hdr->rle_output_size = bytestream2_get_le32u(&ctx->gb);
2243  for (i = 0; i < 256; i++)
2244  ctx->codebook[i] = bytestream2_get_le16u(&ctx->gb);
2245 
2246  bytestream2_skip(&ctx->gb, 8); // skip pad
2247 
2248  return 0;
2249 }
2250 
2251 static void fill_frame(uint16_t *pbuf, int buf_size, uint16_t color)
2252 {
2253  if (buf_size--) {
2254  *pbuf++ = color;
2255  av_memcpy_backptr((uint8_t*)pbuf, 2, 2*buf_size);
2256  }
2257 }
2258 
2260 {
2261  uint8_t *dst;
2262  const uint8_t *src = hdr ? (uint8_t *)ctx->frm0 : (uint8_t *)ctx->fbuf;
2263  int ret, height = ctx->height;
2264  ptrdiff_t dstpitch, srcpitch = ctx->pitch * (hdr ? sizeof(ctx->frm0[0]) : 1);
2265 
2266  if ((ret = ff_get_buffer(ctx->avctx, ctx->frame, 0)) < 0)
2267  return ret;
2268 
2269  dst = ctx->frame->data[0];
2270  dstpitch = ctx->frame->linesize[0];
2271 
2272  while (height--) {
2273  memcpy(dst, src, srcpitch);
2274  src += srcpitch;
2275  dst += dstpitch;
2276  }
2277 
2278  return 0;
2279 }
2280 
2282  int *got_frame_ptr, AVPacket *pkt)
2283 {
2284  SANMVideoContext *ctx = avctx->priv_data;
2285  int i, ret;
2286 
2287  ctx->frame = frame;
2288  bytestream2_init(&ctx->gb, pkt->data, pkt->size);
2289 
2290  if (!ctx->version) {
2291  int to_store = 0, have_img = 0;
2292 
2293  ctx->first_fob = 1;
2294 
2295  while (bytestream2_get_bytes_left(&ctx->gb) >= 8) {
2296  uint32_t sig, size;
2297  int pos;
2298 
2299  sig = bytestream2_get_be32u(&ctx->gb);
2300  size = bytestream2_get_be32u(&ctx->gb);
2301  pos = bytestream2_tell(&ctx->gb);
2302 
2303  if (bytestream2_get_bytes_left(&ctx->gb) < size) {
2304  av_log(avctx, AV_LOG_ERROR, "Incorrect chunk size %"PRIu32".\n", size);
2305  break;
2306  }
2307  switch (sig) {
2308  case MKBETAG('N', 'P', 'A', 'L'):
2309  if (size != PALETTE_SIZE * 3) {
2310  av_log(avctx, AV_LOG_ERROR,
2311  "Incorrect palette block size %"PRIu32".\n", size);
2312  return AVERROR_INVALIDDATA;
2313  }
2314  for (i = 0; i < PALETTE_SIZE; i++)
2315  ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb);
2316  if (ctx->subversion < 2)
2317  ctx->pal[0] = 0xFFU << 24;
2318  break;
2319  case MKBETAG('F', 'O', 'B', 'J'):
2320  if (size < 16)
2321  return AVERROR_INVALIDDATA;
2322  if (ret = process_frame_obj(ctx, &ctx->gb))
2323  return ret;
2324  have_img = 1;
2325 
2326  /* STOR: for ANIMv0/1 store the whole FOBJ datablock, as it
2327  * needs to be replayed on FTCH, since none of the codecs
2328  * it uses work on the full buffer.
2329  * For ANIMv2, it's enough to store the current framebuffer.
2330  */
2331  if (to_store) {
2332  to_store = 0;
2333  if (ctx->subversion < 2) {
2334  if (size + 4 <= ctx->stored_frame_size) {
2335  int pos2 = bytestream2_tell(&ctx->gb);
2336  bytestream2_seek(&ctx->gb, pos, SEEK_SET);
2337  *(uint32_t *)(ctx->stored_frame) = size;
2338  bytestream2_get_bufferu(&ctx->gb, ctx->stored_frame + 4, size);
2339  bytestream2_seek(&ctx->gb, pos2, SEEK_SET);
2340  } else {
2341  av_log(avctx, AV_LOG_ERROR, "FOBJ too large for STOR\n");
2342  ret = AVERROR(ENOMEM);
2343  }
2344  } else {
2345  memcpy(ctx->stored_frame, ctx->fbuf, ctx->buf_size);
2346  }
2347  }
2348  break;
2349  case MKBETAG('X', 'P', 'A', 'L'):
2350  if (ret = process_xpal(ctx, size))
2351  return ret;
2352  break;
2353  case MKBETAG('S', 'T', 'O', 'R'):
2354  to_store = 1;
2355  break;
2356  case MKBETAG('F', 'T', 'C', 'H'):
2357  if (ctx->subversion < 2) {
2358  if (ret = process_ftch(ctx, size))
2359  return ret;
2360  } else {
2361  memcpy(ctx->fbuf, ctx->stored_frame, ctx->buf_size);
2362  }
2363  have_img = 1;
2364  break;
2365  default:
2366  bytestream2_skip(&ctx->gb, size);
2367  av_log(avctx, AV_LOG_DEBUG,
2368  "Unknown/unsupported chunk %"PRIx32".\n", sig);
2369  break;
2370  }
2371 
2372  /* the sizes of chunks are usually a multiple of 2. However
2373  * there are a few unaligned FOBJs in RA1 L2PLAY.ANM only (looks
2374  * like a game bug) and IACT audio chunks which have odd sizes
2375  * but are padded with a zero byte.
2376  */
2377  bytestream2_seek(&ctx->gb, pos + size, SEEK_SET);
2378  if ((pos + size) & 1) {
2379  if (0 != bytestream2_get_byteu(&ctx->gb))
2380  bytestream2_seek(&ctx->gb, pos + size, SEEK_SET);
2381  }
2382  }
2383 
2384  if (have_img) {
2385  if ((ret = copy_output(ctx, NULL)))
2386  return ret;
2387  memcpy(ctx->frame->data[1], ctx->pal, 1024);
2388  *got_frame_ptr = 1;
2389  }
2390  } else {
2392 
2393  if ((ret = read_frame_header(ctx, &header)))
2394  return ret;
2395 
2396  ctx->rotate_code = header.rotate_code;
2397  if (!header.seq_num) {
2398  ctx->frame->flags |= AV_FRAME_FLAG_KEY;
2399  ctx->frame->pict_type = AV_PICTURE_TYPE_I;
2400  fill_frame(ctx->frm1, ctx->npixels, header.bg_color);
2401  fill_frame(ctx->frm2, ctx->npixels, header.bg_color);
2402  } else {
2403  ctx->frame->flags &= ~AV_FRAME_FLAG_KEY;
2404  ctx->frame->pict_type = AV_PICTURE_TYPE_P;
2405  }
2406 
2407  if (header.codec < FF_ARRAY_ELEMS(v1_decoders)) {
2408  if ((ret = v1_decoders[header.codec](ctx))) {
2409  av_log(avctx, AV_LOG_ERROR,
2410  "Subcodec %d: error decoding frame.\n", header.codec);
2411  return ret;
2412  }
2413  } else {
2414  avpriv_request_sample(avctx, "Subcodec %d", header.codec);
2415  return AVERROR_PATCHWELCOME;
2416  }
2417 
2418  if ((ret = copy_output(ctx, &header)))
2419  return ret;
2420 
2421  *got_frame_ptr = 1;
2422 
2423  }
2424  if (ctx->rotate_code)
2425  rotate_bufs(ctx, ctx->rotate_code);
2426 
2427  return pkt->size;
2428 }
2429 
2431  .p.name = "sanm",
2432  CODEC_LONG_NAME("LucasArts SANM/Smush video"),
2433  .p.type = AVMEDIA_TYPE_VIDEO,
2434  .p.id = AV_CODEC_ID_SANM,
2435  .priv_data_size = sizeof(SANMVideoContext),
2436  .init = decode_init,
2437  .close = decode_end,
2439  .p.capabilities = AV_CODEC_CAP_DR1,
2440 };
SANMVideoContext::width
int width
Definition: sanm.c:272
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:737
codec47_read_interptable
static void codec47_read_interptable(SANMVideoContext *ctx)
Definition: sanm.c:1277
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
motion_vectors
static const int8_t motion_vectors[256][2]
Definition: sanm.c:53
SANMVideoContext::fbuf_size
uint32_t fbuf_size
Definition: sanm.c:279
old_codec20
static int old_codec20(SANMVideoContext *ctx, int w, int h)
Definition: sanm.c:986
decode_0
static int decode_0(SANMVideoContext *ctx)
Definition: sanm.c:1883
BOTTOM_EDGE
@ BOTTOM_EDGE
Definition: sanm.c:311
SANMVideoContext::rle_buf
uint8_t * rle_buf
Definition: sanm.c:282
decode_5
static int decode_5(SANMVideoContext *ctx)
Definition: sanm.c:2144
fill_block
static void fill_block(uint16_t *pdest, uint16_t color, int block_size, ptrdiff_t pitch)
Definition: sanm.c:1925
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:389
color
Definition: vf_paletteuse.c:513
process_block
static int process_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *prev1, uint8_t *prev2, int stride, int tbl, int size)
Definition: sanm.c:1187
GetByteContext
Definition: bytestream.h:33
SANMVideoContext::pal
uint32_t pal[PALETTE_SIZE]
Definition: sanm.c:268
bytestream2_tell
static av_always_inline int bytestream2_tell(const GetByteContext *g)
Definition: bytestream.h:192
SANMFrameHeader
Definition: sanm.c:300
SANMVideoContext::stored_frame
uint8_t * stored_frame
Definition: sanm.c:278
SANMVideoContext::aligned_height
int aligned_height
Definition: sanm.c:273
SANMVideoContext::p4x4glyphs
int8_t p4x4glyphs[NGLYPHS][16]
Definition: sanm.c:292
SANMFrameHeader::bg_color
uint16_t bg_color
Definition: sanm.c:303
good_mvec
static int good_mvec(SANMVideoContext *ctx, int cx, int cy, int mx, int my, int block_size)
Definition: sanm.c:2019
mask
int mask
Definition: mediacodecdec_common.c:154
out_size
int out_size
Definition: movenc.c:56
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:912
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:421
w
uint8_t w
Definition: llviddspenc.c:38
AVPacket::data
uint8_t * data
Definition: packet.h:552
decode_end
static av_cold int decode_end(AVCodecContext *avctx)
Definition: sanm.c:662
interp_point
static void interp_point(int8_t *points, int x0, int y0, int x1, int y1, int pos, int npoints)
Definition: sanm.c:369
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
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
decode_3
static int decode_3(SANMVideoContext *ctx)
Definition: sanm.c:2132
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:2430
bit
#define bit(string, value)
Definition: cbs_mpeg2.c:56
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:276
SANMFrameHeader::codec
int codec
Definition: sanm.c:301
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
LEFT_EDGE
@ LEFT_EDGE
Definition: sanm.c:308
glyph8_x
static const int8_t glyph8_x[GLYPH_COORD_VECT_SIZE]
Definition: sanm.c:45
SANMFrameHeader::rotate_code
int rotate_code
Definition: sanm.c:301
SANMVideoContext::gb
GetByteContext gb
Definition: sanm.c:265
destroy_buffers
static void destroy_buffers(SANMVideoContext *ctx)
Definition: sanm.c:454
val
static double val(void *priv, double ch)
Definition: aeval.c:77
loop
static int loop
Definition: ffplay.c:335
decode_2
static int decode_2(SANMVideoContext *ctx)
Definition: sanm.c:2120
SANMVideoContext::small_codebook
uint16_t small_codebook[4]
Definition: sanm.c:290
DIR_LEFT
@ DIR_LEFT
Definition: sanm.c:316
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:330
NO_EDGE
@ NO_EDGE
Definition: sanm.c:312
TOP_EDGE
@ TOP_EDGE
Definition: sanm.c:309
avassert.h
SANMVideoContext::have_dimensions
int have_dimensions
Definition: sanm.c:267
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
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_cold
#define av_cold
Definition: attributes.h:90
SANMFrameHeader::width
uint32_t width
Definition: sanm.c:304
AV_FRAME_FLAG_KEY
#define AV_FRAME_FLAG_KEY
A flag to mark frames that are keyframes.
Definition: frame.h:636
av_memcpy_backptr
void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
Overlapping memcpy() implementation.
Definition: mem.c:447
AVCodecContext::extradata_size
int extradata_size
Definition: avcodec.h:515
codec48_block
static int codec48_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *db, const uint16_t w)
Definition: sanm.c:1430
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:341
SANMFrameHeader::rle_output_size
int rle_output_size
Definition: sanm.c:301
decode_6
static int decode_6(SANMVideoContext *ctx)
Definition: sanm.c:2167
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:1415
SANMVideoContext::npixels
long npixels
Definition: sanm.c:287
bits
uint8_t bits
Definition: vp3data.h:128
old_codec2
static int old_codec2(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int width, int height)
Definition: sanm.c:968
codec47_comp1
static void codec47_comp1(SANMVideoContext *ctx, uint8_t *dst_in, int width, int height, ptrdiff_t stride)
Definition: sanm.c:1293
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:1991
ctx
AVFormatContext * ctx
Definition: movenc.c:49
SANMVideoContext::stored_frame_size
uint32_t stored_frame_size
Definition: sanm.c:280
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
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:326
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
old_codec47
static int old_codec47(SANMVideoContext *ctx, int width, int height)
Definition: sanm.c:1326
GlyphEdge
GlyphEdge
Definition: sanm.c:307
init_sizes
static void init_sizes(SANMVideoContext *ctx, int width, int height)
Definition: sanm.c:441
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
NULL
#define NULL
Definition: coverity.c:32
SANMFrameHeader::height
uint32_t height
Definition: sanm.c:304
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:273
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:763
SANMVideoContext::avctx
AVCodecContext * avctx
Definition: sanm.c:264
SANMVideoContext::subversion
int subversion
Definition: sanm.c:267
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:1935
AV_PICTURE_TYPE_I
@ AV_PICTURE_TYPE_I
Intra.
Definition: avutil.h:278
decode_nop
static int decode_nop(SANMVideoContext *ctx)
Definition: sanm.c:1900
bytestream2_get_buffer
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:267
PALETTE_SIZE
#define PALETTE_SIZE
Definition: sanm.c:34
SANMVideoContext::frm1_size
uint32_t frm1_size
Definition: sanm.c:279
SANMVideoContext::frm1
uint16_t * frm1
Definition: sanm.c:277
rotate_bufs
static void rotate_bufs(SANMVideoContext *ctx, int rotate_code)
Definition: sanm.c:618
process_frame_obj
static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb)
Definition: sanm.c:1641
SANMVideoContext::c47itbl
uint8_t c47itbl[0x10000]
Definition: sanm.c:294
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:551
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:279
ff_get_buffer
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1635
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:553
SANMVideoContext
Definition: sanm.c:263
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:1004
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
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:424
decode_4
static int decode_4(SANMVideoContext *ctx)
Definition: sanm.c:2138
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:267
SANMVideoContext::frm0
uint16_t * frm0
Definition: sanm.c:277
header
static const uint8_t header[24]
Definition: sdr2.c:68
av_le2ne16
#define av_le2ne16(x)
Definition: bswap.h:91
SANMVideoContext::c4param
uint16_t c4param
Definition: sanm.c:297
SANMVideoContext::c23lut
uint8_t c23lut[256]
Definition: sanm.c:295
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:671
decode_init
static av_cold int decode_init(AVCodecContext *avctx)
Definition: sanm.c:625
xf
#define xf(width, name, var, range_min, range_max, subs,...)
Definition: cbs_av1.c:621
old_codec37
static int old_codec37(SANMVideoContext *ctx, int width, int height)
Definition: sanm.c:1023
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
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:632
fill_frame
static void fill_frame(uint16_t *pbuf, int buf_size, uint16_t color)
Definition: sanm.c:2251
copy_block.h
copy_block
static void copy_block(uint16_t *pdest, uint16_t *psrc, int block_size, ptrdiff_t pitch)
Definition: sanm.c:1906
AVCodecContext::extradata
uint8_t * extradata
Out-of-band global headers that may be used by some codecs.
Definition: avcodec.h:514
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
process_xpal
static int process_xpal(SANMVideoContext *ctx, int size)
Definition: sanm.c:1842
SANMFrameHeader::seq_num
int seq_num
Definition: sanm.c:301
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:179
SANMVideoContext::fbuf
uint16_t * fbuf
Definition: sanm.c:277
SANMVideoContext::first_fob
int first_fob
Definition: sanm.c:267
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
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:289
read_frame_header
static int read_frame_header(SANMVideoContext *ctx, SANMFrameHeader *hdr)
Definition: sanm.c:2211
GlyphDir
GlyphDir
Definition: sanm.c:315
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:319
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:277
DIR_RIGHT
@ DIR_RIGHT
Definition: sanm.c:318
pos
unsigned int pos
Definition: spdifenc.c:414
c37_mv
static const int8_t c37_mv[]
Definition: sanm.c:107
flag
#define flag(name)
Definition: cbs_av1.c:495
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:819
AVCodecContext
main external API structure.
Definition: avcodec.h:431
copy_output
static int copy_output(SANMVideoContext *ctx, SANMFrameHeader *hdr)
Definition: sanm.c:2259
SANMVideoContext::rle_buf_size
unsigned int rle_buf_size
Definition: sanm.c:283
SANMVideoContext::buf_size
long buf_size
Definition: sanm.c:287
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:346
SANMVideoContext::c4tbl
uint8_t c4tbl[2][256][16]
Definition: sanm.c:296
old_codec48
static int old_codec48(SANMVideoContext *ctx, int width, int height)
Definition: sanm.c:1561
codec4_load_tiles
static int codec4_load_tiles(SANMVideoContext *ctx, GetByteContext *gb, uint16_t param2, uint8_t clr)
Definition: sanm.c:600
av_clip_uint8
#define av_clip_uint8
Definition: common.h:106
RIGHT_EDGE
@ RIGHT_EDGE
Definition: sanm.c:310
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:293
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:1957
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AVPacket
This structure stores compressed data.
Definition: packet.h:529
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:487
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
codec2subblock
static int codec2subblock(SANMVideoContext *ctx, int cx, int cy, int blk_size)
Definition: sanm.c:2035
frm_decoder
int(* frm_decoder)(SANMVideoContext *ctx)
Definition: sanm.c:2204
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:317
v1_decoders
static const frm_decoder v1_decoders[]
Definition: sanm.c:2206
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:1793
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:862
SANMVideoContext::delta_pal
int16_t delta_pal[PALETTE_DELTA]
Definition: sanm.c:269
NO_DIR
@ NO_DIR
Definition: sanm.c:320
width
#define width
Definition: dsp.h:89
av_bswap16
#define av_bswap16
Definition: bswap.h:28
SANMVideoContext::rotate_code
int rotate_code
Definition: sanm.c:285
SANMVideoContext::pitch
ptrdiff_t pitch
Definition: sanm.c:271
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:279
SANMVideoContext::prev_seq
int prev_seq
Definition: sanm.c:274
SANMVideoContext::height
int height
Definition: sanm.c:272
decode_8
static int decode_8(SANMVideoContext *ctx)
Definition: sanm.c:2182
decode_frame
static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *pkt)
Definition: sanm.c:2281
init_buffers
static av_cold int init_buffers(SANMVideoContext *ctx)
Definition: sanm.c:468