FFmpeg
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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 *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->frm0);
457  av_freep(&ctx->frm1);
458  av_freep(&ctx->frm2);
459  av_freep(&ctx->stored_frame);
460  av_freep(&ctx->rle_buf);
461  ctx->frm0_size =
462  ctx->frm1_size =
463  ctx->frm2_size = 0;
464  init_sizes(ctx, 0, 0);
465 }
466 
468 {
469  av_fast_padded_mallocz(&ctx->frm0, &ctx->frm0_size, ctx->buf_size);
470  av_fast_padded_mallocz(&ctx->frm1, &ctx->frm1_size, ctx->buf_size);
471  av_fast_padded_mallocz(&ctx->frm2, &ctx->frm2_size, ctx->buf_size);
472  if (!ctx->version)
473  av_fast_padded_mallocz(&ctx->stored_frame,
474  &ctx->stored_frame_size, ctx->buf_size);
475 
476  if (!ctx->frm0 || !ctx->frm1 || !ctx->frm2 ||
477  (!ctx->stored_frame && !ctx->version)) {
479  return AVERROR(ENOMEM);
480  }
481 
482  return 0;
483 }
484 
485 static void codec33_gen_tiles(SANMVideoContext *ctx, int8_t param1)
486 {
487  uint8_t *dst = &(ctx->c4tbl[0][0][0]);
488  int i, j, k, l, m, n, o, p;
489 
490  for (i = 0; i < 8; i++) {
491  for (k = 0; k < 8; k++) {
492  j = i + param1;
493  l = k + param1;
494  p = (j + k) / 2;
495  j = (j + p) / 2;
496  m = l / 2;
497  n = (i + param1);
498  o = (k + param1);
499 
500  *dst++ = p; *dst++ = p; *dst++ = j; *dst++ = n;
501  *dst++ = p; *dst++ = p; *dst++ = j; *dst++ = i;
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) / 2);
512  m = ((l + n) / 2);
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) / 2;
526  n = (j + m) / 2;
527  o = m / 2;
528  p = j & 0xff;
529 
530  *dst++ = p; *dst++ = p; *dst++ = n; *dst++ = m;
531  *dst++ = p; *dst++ = p; *dst++ = n; *dst++ = m;
532  *dst++ = n; *dst++ = n; *dst++ = m; *dst++ = o;
533  *dst++ = m; *dst++ = m; *dst++ = o; *dst++ = l;
534  }
535  }
536 
537  for (i = 0; i < 8; i++) {
538  for (k = 0; k < 8; k++) {
539  j = i + param1;
540  l = k + param1;
541  m = (j + l) / 2;
542  n = m / 2;
543 
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  *dst++ = j; *dst++ = m; *dst++ = n; *dst++ = l;
548  }
549  }
550 }
551 
552 static void codec4_gen_tiles(SANMVideoContext *ctx, uint16_t param1)
553 {
554  uint8_t *dst = &(ctx->c4tbl[0][0][0]);
555  int i, j, k, l, m, n, o;
556 
557  for (i = 1; i < 16; i += 2) {
558  for (k = 0; k < 16; k++) {
559  j = i + param1;
560  l = k + param1;
561  m = (j + l) / 2;
562  n = (j + m) / 2;
563  o = (l + m) / 2;
564  if (j == m || l == m) {
565  *dst++ = l; *dst++ = j; *dst++ = l; *dst++ = j;
566  *dst++ = j; *dst++ = l; *dst++ = j; *dst++ = j;
567  *dst++ = l; *dst++ = j; *dst++ = l; *dst++ = j;
568  *dst++ = l; *dst++ = l; *dst++ = j; *dst++ = l;
569  } else {
570  *dst++ = m; *dst++ = m; *dst++ = n; *dst++ = j;
571  *dst++ = m; *dst++ = m; *dst++ = n; *dst++ = j;
572  *dst++ = o; *dst++ = o; *dst++ = m; *dst++ = n;
573  *dst++ = l; *dst++ = l; *dst++ = o; *dst++ = m;
574  }
575  }
576  }
577 
578  for (i = 0; i < 16; i += 2) {
579  for (k = 0; k < 16; k++) {
580  j = i + param1;
581  l = k + param1;
582  m = (j + l) / 2;
583  n = (j + m) / 2;
584  o = (l + m) / 2;
585  if (m == j || m == l) {
586  *dst++ = j; *dst++ = j; *dst++ = l; *dst++ = j;
587  *dst++ = j; *dst++ = j; *dst++ = j; *dst++ = l;
588  *dst++ = l; *dst++ = j; *dst++ = l; *dst++ = l;
589  *dst++ = j; *dst++ = l; *dst++ = j; *dst++ = l;
590  } else {
591  *dst++ = j; *dst++ = j; *dst++ = n; *dst++ = m;
592  *dst++ = j; *dst++ = j; *dst++ = n; *dst++ = m;
593  *dst++ = n; *dst++ = n; *dst++ = m; *dst++ = o;
594  *dst++ = m; *dst++ = m; *dst++ = o; *dst++ = l;
595  }
596  }
597  }
598 }
599 
600 
602  uint16_t param2, uint8_t clr)
603 {
604  uint8_t c, *dst = (uint8_t *)&(ctx->c4tbl[1][0][0]);
605  uint32_t loop = param2 * 8;
606 
607  if ((param2 > 256) || (bytestream2_get_bytes_left(gb) < loop))
608  return AVERROR_INVALIDDATA;
609 
610  while (loop--) {
611  c = bytestream2_get_byteu(gb);
612  *dst++ = (c >> 4) + clr;
613  *dst++ = (c & 0xf) + clr;
614  }
615 
616  return 0;
617 }
618 
619 static void rotate_bufs(SANMVideoContext *ctx, int rotate_code)
620 {
621  if (rotate_code == 2)
622  FFSWAP(uint16_t*, ctx->frm1, ctx->frm2);
623  FFSWAP(uint16_t*, ctx->frm2, ctx->frm0);
624 }
625 
627 {
628  SANMVideoContext *ctx = avctx->priv_data;
629 
630  ctx->avctx = avctx;
631  ctx->version = !avctx->extradata_size;
632  // early sanity check before allocations to avoid need for deallocation code.
633  if (!ctx->version && avctx->extradata_size < 1026) {
634  av_log(avctx, AV_LOG_ERROR, "Not enough extradata.\n");
635  return AVERROR_INVALIDDATA;
636  }
637 
638  avctx->pix_fmt = ctx->version ? AV_PIX_FMT_RGB565 : AV_PIX_FMT_PAL8;
639 
640  init_sizes(ctx, avctx->width, avctx->height);
641  if (init_buffers(ctx)) {
642  av_log(avctx, AV_LOG_ERROR, "Error allocating buffers.\n");
643  return AVERROR(ENOMEM);
644  }
645 
646  make_glyphs(ctx->p4x4glyphs[0], glyph4_x, glyph4_y, 4);
647  make_glyphs(ctx->p8x8glyphs[0], glyph8_x, glyph8_y, 8);
648 
649  if (!ctx->version) {
650  int i;
651 
652  ctx->subversion = AV_RL16(avctx->extradata);
653  for (i = 0; i < PALETTE_SIZE; i++)
654  ctx->pal[i] = 0xFFU << 24 | AV_RL32(avctx->extradata + 2 + i * 4);
655  if (ctx->subversion < 2)
656  ctx->pal[0] = 0xFFU << 24;
657  }
658  ctx->c4param = 0xffff;
659 
660  return 0;
661 }
662 
664 {
665  SANMVideoContext *ctx = avctx->priv_data;
666 
668 
669  return 0;
670 }
671 
672 static int old_codec4(SANMVideoContext *ctx, GetByteContext *gb, int top, int left,
673  int w, int h, uint8_t param, uint16_t param2, int codec)
674 {
675  const uint16_t p = ctx->pitch;
676  const uint32_t maxpxo = ctx->height * p;
677  uint8_t mask, bits, idx, *gs, *dst = (uint8_t *)ctx->frm0;
678  int i, j, k, l, bit, ret;
679  int32_t pxoff, pxo2;
680 
681  if (ctx->c4param != param) {
682  if (codec > 32)
683  codec33_gen_tiles(ctx, param);
684  else
685  codec4_gen_tiles(ctx, param);
686  ctx->c4param = param;
687  }
688  if (param2 > 0) {
689  ret = codec4_load_tiles(ctx, gb, param2, param);
690  if (ret)
691  return ret;
692  }
693 
694  if (codec > 32)
695  codec -= 29;
696 
697  for (j = 0; j < w; j += 4) {
698  mask = bits = 0;
699  for (i = 0; i < h; i += 4) {
700  pxoff = j + left + ((top + i) * p);
701  if (param2 > 0) {
702  if (bits == 0) {
703  if (bytestream2_get_bytes_left(gb) < 1)
704  return AVERROR_INVALIDDATA;
705  mask = bytestream2_get_byteu(gb);
706  bits = 8;
707  }
708  bit = !!(mask & 0x80);
709  mask <<= 1;
710  bits--;
711  } else {
712  bit = 0;
713  }
714 
715  if (bytestream2_get_bytes_left(gb) < 1)
716  return AVERROR_INVALIDDATA;
717  idx = bytestream2_get_byteu(gb);
718  if ((bit == 0) && (idx == 0x80) && (codec != 5))
719  continue;
720 
721  gs = &(ctx->c4tbl[bit][idx][0]);
722  pxo2 = pxoff;
723  for (k = 0; k < 4; k++) {
724  for (l = 0; l < 4; l++) {
725  if (pxo2 >= 0 && pxo2 < maxpxo) {
726  *(dst + pxo2) = *gs;
727  }
728  gs++;
729  pxo2++;
730  }
731  pxo2 = pxo2 - 4 + p;
732  }
733 
734  /* smooth top and left block borders with neighbours */
735  if (((pxoff - p + k) < 0) || ((pxoff - p + k) >= maxpxo)
736  || ((pxoff + 3 * p) < 0) || ((pxoff + 3 * p) >= maxpxo)
737  || (i == 0) || (j == 0))
738  continue;
739  if (param & 0x80) {
740  for (k = 0; k < 4; k++)
741  *(dst + pxoff + k) = ((*(dst + pxoff + k) + *(dst + pxoff - p + k)) >> 1) | 0x80;
742  *(dst + pxoff + 1 * p) = (*(dst + pxoff + 1 * p) + *(dst + pxoff + 1 * p - 1)) >> 1 | 0x80;
743  *(dst + pxoff + 2 * p) = (*(dst + pxoff + 2 * p) + *(dst + pxoff + 2 * p - 1)) >> 1 | 0x80;
744  *(dst + pxoff + 3 * p) = (*(dst + pxoff + 3 * p) + *(dst + pxoff + 3 * p - 1)) >> 1 | 0x80;
745  } else {
746  for (k = 0; k < 4; k++)
747  *(dst + pxoff + k) = ((*(dst + pxoff + k) + *(dst + pxoff - p + k)) >> 1) & 0x7f;
748  *(dst + pxoff + 1 * p) = (*(dst + pxoff + 1 * p) + *(dst + pxoff + 1 * p - 1)) >> 1;
749  *(dst + pxoff + 2 * p) = (*(dst + pxoff + 2 * p) + *(dst + pxoff + 2 * p - 1)) >> 1;
750  *(dst + pxoff + 3 * p) = (*(dst + pxoff + 3 * p) + *(dst + pxoff + 3 * p - 1)) >> 1;
751  }
752  }
753  }
754  return 0;
755 }
756 
757 static int rle_decode(SANMVideoContext *ctx, GetByteContext *gb, uint8_t *dst, const int out_size)
758 {
759  int opcode, color, run_len, left = out_size;
760 
761  while (left > 0) {
762  opcode = bytestream2_get_byte(gb);
763  run_len = (opcode >> 1) + 1;
764  if (run_len > left || bytestream2_get_bytes_left(gb) <= 0)
765  return AVERROR_INVALIDDATA;
766 
767  if (opcode & 1) {
768  color = bytestream2_get_byte(gb);
769  memset(dst, color, run_len);
770  } else {
772  return AVERROR_INVALIDDATA;
774  }
775 
776  dst += run_len;
777  left -= run_len;
778  }
779 
780  return 0;
781 }
782 
783 static int old_codec23(SANMVideoContext *ctx, GetByteContext *gb, int top, int left,
784  int width, int height, uint8_t param, uint16_t param2)
785 {
786  const uint32_t maxpxo = ctx->height * ctx->pitch;
787  uint8_t *dst, lut[256], c;
788  int i, j, k, pc, sk;
789  int32_t pxoff;
790 
791  if (ctx->subversion < 2) {
792  /* Rebel Assault 1: constant offset + 0xd0 */
793  for (i = 0; i < 256; i++)
794  lut[i] = (i + param + 0xd0) & 0xff;
795  } else if (param2 == 256) {
796  if (bytestream2_get_bytes_left(gb) < 256)
797  return AVERROR_INVALIDDATA;
798  bytestream2_get_bufferu(gb, ctx->c23lut, 256);
799  } else if (param2 < 256) {
800  for (i = 0; i < 256; i++)
801  lut[i] = (i + param2) & 0xff;
802  } else {
803  memcpy(lut, ctx->c23lut, 256);
804  }
805  if (bytestream2_get_bytes_left(gb) < 1)
806  return 0; /* some c23 frames just set up the LUT */
807 
808  dst = (uint8_t *)ctx->frm0;
809  for (i = 0; i < height; i++) {
810  if (bytestream2_get_bytes_left(gb) < 2)
811  return 0;
812  pxoff = left + ((top + i) * ctx->pitch);
813  k = bytestream2_get_le16u(gb);
814  sk = 1;
815  pc = 0;
816  while (k > 0 && pc <= width) {
817  if (bytestream2_get_bytes_left(gb) < 1)
818  return AVERROR_INVALIDDATA;
819  j = bytestream2_get_byteu(gb);
820  if (sk) {
821  pxoff += j;
822  pc += j;
823  } else {
824  while (j--) {
825  if (pxoff >=0 && pxoff < maxpxo) {
826  c = *(dst + pxoff);
827  *(dst + pxoff) = lut[c];
828  }
829  pxoff++;
830  pc++;
831  }
832  }
833  sk ^= 1;
834  }
835  }
836  return 0;
837 }
838 
839 static int old_codec21(SANMVideoContext *ctx, GetByteContext *gb, int top, int left,
840  int width, int height)
841 {
842  const uint32_t maxpxo = ctx->height * ctx->pitch;
843  uint8_t *dst = (uint8_t *)ctx->frm0, c;
844  int i, j, k, pc, sk, pxoff;
845 
846  dst = (uint8_t *)ctx->frm0;
847  for (i = 0; i < height; i++) {
848  if (bytestream2_get_bytes_left(gb) < 2)
849  return 0;
850  pxoff = left + ((top + i) * ctx->pitch);
851  k = bytestream2_get_le16u(gb);
852  sk = 1;
853  pc = 0;
854  while (k > 0 && pc <= width) {
855  if (bytestream2_get_bytes_left(gb) < 2)
856  return AVERROR_INVALIDDATA;
857  j = bytestream2_get_le16u(gb);
858  k -= 2;
859  if (sk) {
860  pxoff += j;
861  pc += j;
862  } else {
863  if (bytestream2_get_bytes_left(gb) < (j + 1))
864  return AVERROR_INVALIDDATA;
865  do {
866  c = bytestream2_get_byteu(gb);
867  if (pxoff >=0 && pxoff < maxpxo) {
868  *(dst + pxoff) = c;
869  }
870  pxoff++;
871  pc++;
872  j--;
873  k--;
874  } while (j > -1);
875  }
876  sk ^= 1;
877  }
878  }
879  return 0;
880 }
881 
882 static int old_codec1(SANMVideoContext *ctx, GetByteContext *gb, int top,
883  int left, int width, int height, int opaque)
884 {
885  int i, j, len, flag, code, val, end, pxoff;
886  const int maxpxo = ctx->height * ctx->pitch;
887  uint8_t *dst = (uint8_t *)ctx->frm0;
888 
889  for (i = 0; i < height; i++) {
890  if (bytestream2_get_bytes_left(gb) < 2)
891  return AVERROR_INVALIDDATA;
892 
893  len = bytestream2_get_le16u(gb);
894  end = bytestream2_tell(gb) + len;
895 
896  pxoff = left + ((top + i) * ctx->pitch);
897  while (bytestream2_tell(gb) < end) {
898  if (bytestream2_get_bytes_left(gb) < 2)
899  return AVERROR_INVALIDDATA;
900 
901  code = bytestream2_get_byteu(gb);
902  flag = code & 1;
903  code = (code >> 1) + 1;
904  if (flag) {
905  val = bytestream2_get_byteu(gb);
906  if (val || opaque) {
907  for (j = 0; j < code; j++) {
908  if (pxoff >= 0 && pxoff < maxpxo)
909  *(dst + pxoff) = val;
910  pxoff++;
911  }
912  } else {
913  pxoff += code;
914  }
915  } else {
917  return AVERROR_INVALIDDATA;
918  for (j = 0; j < code; j++) {
919  val = bytestream2_get_byteu(gb);
920  if ((pxoff >= 0) && (pxoff < maxpxo) && (val || opaque))
921  *(dst + pxoff) = val;
922  pxoff++;
923  }
924  }
925  }
926  }
927  ctx->rotate_code = 0;
928 
929  return 0;
930 }
931 
932 static int old_codec2(SANMVideoContext *ctx, GetByteContext *gb, int top,
933  int left, int width, int height)
934 {
935  uint8_t *dst = (uint8_t *)ctx->frm0, col;
936  int16_t xpos = left, ypos = top;
937 
938  while (bytestream2_get_bytes_left(gb) > 3) {
939  xpos += bytestream2_get_le16u(gb);
940  ypos += bytestream2_get_byteu(gb);
941  col = bytestream2_get_byteu(gb);
942  if (xpos >= 0 && ypos >= 0 &&
943  xpos < ctx->width && ypos < ctx->height) {
944  *(dst + xpos + ypos * ctx->pitch) = col;
945  }
946  }
947  return 0;
948 }
949 
950 static int old_codec20(SANMVideoContext *ctx, int w, int h)
951 {
952  uint8_t *dst = (uint8_t *)ctx->frm0;
953 
954  if (bytestream2_get_bytes_left(&ctx->gb) < w * h)
955  return AVERROR_INVALIDDATA;
956 
957  if (w == ctx->pitch) {
958  bytestream2_get_bufferu(&ctx->gb, dst, w * h);
959  } else {
960  for (int i = 0; i < h; i++) {
962  dst += ctx->pitch;
963  }
964  }
965  return 0;
966 }
967 
968 static inline void codec37_mv(uint8_t *dst, const uint8_t *src,
969  int height, int stride, int x, int y)
970 {
971  int pos, i, j;
972 
973  pos = x + y * stride;
974  for (j = 0; j < 4; j++) {
975  for (i = 0; i < 4; i++) {
976  if ((pos + i) < 0 || (pos + i) >= height * stride)
977  dst[i] = 0;
978  else
979  dst[i] = src[i];
980  }
981  dst += stride;
982  src += stride;
983  pos += stride;
984  }
985 }
986 
988 {
989  int i, j, k, l, t, run, len, code, skip, mx, my;
990  ptrdiff_t stride = ctx->pitch;
991  uint8_t *dst, *prev;
992  int skip_run = 0;
993  int compr = bytestream2_get_byte(&ctx->gb);
994  int mvoff = bytestream2_get_byte(&ctx->gb);
995  int seq = bytestream2_get_le16(&ctx->gb);
996  uint32_t decoded_size = bytestream2_get_le32(&ctx->gb);
997  int flags;
998 
999  bytestream2_skip(&ctx->gb, 4);
1000  flags = bytestream2_get_byte(&ctx->gb);
1001  bytestream2_skip(&ctx->gb, 3);
1002 
1003  if (decoded_size > ctx->height * stride) {
1004  decoded_size = ctx->height * stride;
1005  av_log(ctx->avctx, AV_LOG_WARNING, "Decoded size is too large.\n");
1006  }
1007 
1008  ctx->rotate_code = 0;
1009 
1010  if (((seq & 1) || !(flags & 1)) && (compr && compr != 2)) {
1011  FFSWAP(uint16_t*, ctx->frm1, ctx->frm2);
1012  }
1013 
1014  dst = ((uint8_t*)ctx->frm1);
1015  prev = ((uint8_t*)ctx->frm2);
1016 
1017  if (mvoff > 2) {
1018  av_log(ctx->avctx, AV_LOG_ERROR, "Invalid motion base value %d.\n", mvoff);
1019  return AVERROR_INVALIDDATA;
1020  }
1021 
1022  switch (compr) {
1023  case 0:
1024  for (i = 0; i < height; i++) {
1026  dst += stride;
1027  }
1028  memset(ctx->frm2, 0, ctx->height * stride);
1029  break;
1030  case 1:
1031  run = 0;
1032  len = -1;
1033  code = 0;
1034 
1035  for (j = 0; j < height; j += 4) {
1036  for (i = 0; i < width; i += 4) {
1037  if (len < 0) {
1038  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1039  return AVERROR_INVALIDDATA;
1040  code = bytestream2_get_byte(&ctx->gb);
1041  len = code >> 1;
1042  run = code & 1;
1043  skip = 0;
1044  } else {
1045  skip = run;
1046  }
1047 
1048  if (!skip) {
1049  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1050  return AVERROR_INVALIDDATA;
1051  code = bytestream2_get_byte(&ctx->gb);
1052  if (code == 0xff) {
1053  len--;
1054  for (k = 0; k < 4; k++) {
1055  for (l = 0; l < 4; l++) {
1056  if (len < 0) {
1057  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1058  return AVERROR_INVALIDDATA;
1059  code = bytestream2_get_byte(&ctx->gb);
1060  len = code >> 1;
1061  run = code & 1;
1062  if (run) {
1063  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1064  return AVERROR_INVALIDDATA;
1065  code = bytestream2_get_byte(&ctx->gb);
1066  }
1067  }
1068  if (!run) {
1069  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1070  return AVERROR_INVALIDDATA;
1071  code = bytestream2_get_byte(&ctx->gb);
1072  }
1073  *(dst + i + (k * stride) + l) = code;
1074  len--;
1075  }
1076  }
1077  continue;
1078  }
1079  }
1080  /* 4x4 block copy from prev with MV */
1081  mx = c37_mv[(mvoff * 255 + code) * 2];
1082  my = c37_mv[(mvoff * 255 + code) * 2 + 1];
1083  codec37_mv(dst + i, prev + i + mx + my * stride,
1084  ctx->height, stride, i + mx, j + my);
1085  len--;
1086  }
1087  dst += stride * 4;
1088  prev += stride * 4;
1089  }
1090  break;
1091  case 2:
1092  if (rle_decode(ctx, &ctx->gb, dst, decoded_size))
1093  return AVERROR_INVALIDDATA;
1094  memset(ctx->frm2, 0, ctx->frm2_size);
1095  break;
1096  case 3:
1097  case 4:
1098  for (j = 0; j < height; j += 4) {
1099  for (i = 0; i < width; i += 4) {
1100  int code;
1101  if (skip_run) {
1102  skip_run--;
1103  copy_block4(dst + i, prev + i, stride, stride, 4);
1104  continue;
1105  }
1106  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1107  return AVERROR_INVALIDDATA;
1108  code = bytestream2_get_byteu(&ctx->gb);
1109  if (code == 0xFF) {
1110  if (bytestream2_get_bytes_left(&ctx->gb) < 16)
1111  return AVERROR_INVALIDDATA;
1112  for (k = 0; k < 4; k++)
1113  bytestream2_get_bufferu(&ctx->gb, dst + i + k * stride, 4);
1114  } else if ((flags & 4) && (code == 0xFE)) {
1115  if (bytestream2_get_bytes_left(&ctx->gb) < 4)
1116  return AVERROR_INVALIDDATA;
1117  for (k = 0; k < 4; k++)
1118  memset(dst + i + k * stride, bytestream2_get_byteu(&ctx->gb), 4);
1119  } else if ((flags & 4) && (code == 0xFD)) {
1120  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1121  return AVERROR_INVALIDDATA;
1122  t = bytestream2_get_byteu(&ctx->gb);
1123  for (k = 0; k < 4; k++)
1124  memset(dst + i + k * stride, t, 4);
1125  } else {
1126  mx = c37_mv[(mvoff * 255 + code) * 2];
1127  my = c37_mv[(mvoff * 255 + code) * 2 + 1];
1128  codec37_mv(dst + i, prev + i + mx + my * stride,
1129  ctx->height, stride, i + mx, j + my);
1130 
1131  if ((compr == 4) && (code == 0)) {
1132  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1133  return AVERROR_INVALIDDATA;
1134  skip_run = bytestream2_get_byteu(&ctx->gb);
1135  }
1136  }
1137  }
1138  dst += stride * 4;
1139  prev += stride * 4;
1140  }
1141  break;
1142  default:
1144  "Subcodec 37 compression %d", compr);
1145  return AVERROR_PATCHWELCOME;
1146  }
1147 
1148  memcpy(ctx->frm0, ctx->frm1, ctx->buf_size);
1149  return 0;
1150 }
1151 
1152 static int process_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *prev1,
1153  uint8_t *prev2, int stride, int tbl, int size)
1154 {
1155  int code, k, t;
1156  uint8_t colors[2];
1157  int8_t *pglyph;
1158 
1159  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1160  return AVERROR_INVALIDDATA;
1161 
1162  code = bytestream2_get_byteu(&ctx->gb);
1163  if (code >= 0xF8) {
1164  switch (code) {
1165  case 0xFF:
1166  if (size == 2) {
1167  if (bytestream2_get_bytes_left(&ctx->gb) < 4)
1168  return AVERROR_INVALIDDATA;
1169  dst[0] = bytestream2_get_byteu(&ctx->gb);
1170  dst[1] = bytestream2_get_byteu(&ctx->gb);
1171  dst[0 + stride] = bytestream2_get_byteu(&ctx->gb);
1172  dst[1 + stride] = bytestream2_get_byteu(&ctx->gb);
1173  } else {
1174  size >>= 1;
1175  if (process_block(ctx, dst, prev1, prev2, stride, tbl, size))
1176  return AVERROR_INVALIDDATA;
1177  if (process_block(ctx, dst + size, prev1 + size, prev2 + size,
1178  stride, tbl, size))
1179  return AVERROR_INVALIDDATA;
1180  dst += size * stride;
1181  prev1 += size * stride;
1182  prev2 += size * stride;
1183  if (process_block(ctx, dst, prev1, prev2, stride, tbl, size))
1184  return AVERROR_INVALIDDATA;
1185  if (process_block(ctx, dst + size, prev1 + size, prev2 + size,
1186  stride, tbl, size))
1187  return AVERROR_INVALIDDATA;
1188  }
1189  break;
1190  case 0xFE:
1191  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1192  return AVERROR_INVALIDDATA;
1193 
1194  t = bytestream2_get_byteu(&ctx->gb);
1195  for (k = 0; k < size; k++)
1196  memset(dst + k * stride, t, size);
1197  break;
1198  case 0xFD:
1199  if (bytestream2_get_bytes_left(&ctx->gb) < 3)
1200  return AVERROR_INVALIDDATA;
1201 
1202  code = bytestream2_get_byteu(&ctx->gb);
1203  pglyph = (size == 8) ? ctx->p8x8glyphs[code] : ctx->p4x4glyphs[code];
1204  bytestream2_get_bufferu(&ctx->gb, colors, 2);
1205 
1206  for (k = 0; k < size; k++)
1207  for (t = 0; t < size; t++)
1208  dst[t + k * stride] = colors[!*pglyph++];
1209  break;
1210  case 0xFC:
1211  for (k = 0; k < size; k++)
1212  memcpy(dst + k * stride, prev1 + k * stride, size);
1213  break;
1214  default:
1215  k = bytestream2_tell(&ctx->gb);
1216  bytestream2_seek(&ctx->gb, tbl + (code & 7), SEEK_SET);
1217  t = bytestream2_get_byte(&ctx->gb);
1218  bytestream2_seek(&ctx->gb, k, SEEK_SET);
1219  for (k = 0; k < size; k++)
1220  memset(dst + k * stride, t, size);
1221  }
1222  } else {
1223  int mx = motion_vectors[code][0];
1224  int my = motion_vectors[code][1];
1225  int index = prev2 - (const uint8_t *)ctx->frm2;
1226 
1227  av_assert2(index >= 0 && index < (ctx->buf_size >> 1));
1228 
1229  if (index < -mx - my * stride ||
1230  (ctx->buf_size >> 1) - index < mx + size + (my + size - 1) * stride) {
1231  av_log(ctx->avctx, AV_LOG_ERROR, "MV is invalid.\n");
1232  return AVERROR_INVALIDDATA;
1233  }
1234 
1235  for (k = 0; k < size; k++)
1236  memcpy(dst + k * stride, prev2 + mx + (my + k) * stride, size);
1237  }
1238 
1239  return 0;
1240 }
1241 
1243 {
1244  uint8_t *p1, *p2, *itbl = ctx->c47itbl;
1245  int i, j;
1246 
1247  for (i = 0; i < 256; i++) {
1248  p1 = p2 = itbl + i;
1249  for (j = 256 - i; j; j--) {
1250  *p1 = *p2 = bytestream2_get_byte(&ctx->gb);
1251  p1 += 1;
1252  p2 += 256;
1253  }
1254  itbl += 256;
1255  }
1256 }
1257 
1258 static void codec47_comp1(SANMVideoContext *ctx, uint8_t *dst_in, int width,
1259  int height, ptrdiff_t stride)
1260 {
1261  uint8_t p1, *dst, *itbl = ctx->c47itbl;
1262  uint16_t px;
1263  int i, j;
1264 
1265  dst = dst_in + stride;
1266  for (i = 0; i < height; i += 2) {
1267  p1 = bytestream2_get_byte(&ctx->gb);
1268  *dst++ = p1;
1269  *dst++ = p1;
1270  px = p1;
1271  for (j = 2; j < width; j += 2) {
1272  p1 = bytestream2_get_byte(&ctx->gb);
1273  px = (px << 8) | p1;
1274  *dst++ = itbl[px];
1275  *dst++ = p1;
1276  }
1277  dst += stride;
1278  }
1279 
1280  memcpy(dst_in, dst_in + stride, width);
1281  dst = dst_in + stride + stride;
1282  for (i = 2; i < height - 1; i += 2) {
1283  for (j = 0; j < width; j++) {
1284  px = (*(dst - stride) << 8) | *(dst + stride);
1285  *dst++ = itbl[px];
1286  }
1287  dst += stride;
1288  }
1289 }
1290 
1292 {
1293  uint32_t decoded_size;
1294  int i, j;
1295  ptrdiff_t stride = ctx->pitch;
1296  uint8_t *dst = (uint8_t *)ctx->frm0;
1297  uint8_t *prev1 = (uint8_t *)ctx->frm1;
1298  uint8_t *prev2 = (uint8_t *)ctx->frm2;
1299  uint8_t auxcol[2];
1300  int tbl_pos = bytestream2_tell(&ctx->gb);
1301  int seq = bytestream2_get_le16(&ctx->gb);
1302  int compr = bytestream2_get_byte(&ctx->gb);
1303  int new_rot = bytestream2_get_byte(&ctx->gb);
1304  int skip = bytestream2_get_byte(&ctx->gb);
1305 
1306  bytestream2_skip(&ctx->gb, 7);
1307  auxcol[0] = bytestream2_get_byteu(&ctx->gb);
1308  auxcol[1] = bytestream2_get_byteu(&ctx->gb);
1309  decoded_size = bytestream2_get_le32(&ctx->gb);
1310  bytestream2_skip(&ctx->gb, 8);
1311 
1312  if (decoded_size > ctx->height * stride) {
1313  decoded_size = ctx->height * stride;
1314  av_log(ctx->avctx, AV_LOG_WARNING, "Decoded size is too large.\n");
1315  }
1316 
1317  if (skip & 1) {
1318  if (bytestream2_get_bytes_left(&ctx->gb) < 0x8080)
1319  return AVERROR_INVALIDDATA;
1321  }
1322  if (!seq) {
1323  ctx->prev_seq = -1;
1324  memset(prev1, auxcol[0], ctx->height * stride);
1325  memset(prev2, auxcol[1], ctx->height * stride);
1326  }
1327 
1328  switch (compr) {
1329  case 0:
1331  return AVERROR_INVALIDDATA;
1332  for (j = 0; j < height; j++) {
1334  dst += stride;
1335  }
1336  break;
1337  case 1:
1338  if (bytestream2_get_bytes_left(&ctx->gb) < ((width + 1) >> 1) * ((height + 1) >> 1))
1339  return AVERROR_INVALIDDATA;
1341  break;
1342  case 2:
1343  if (seq == ctx->prev_seq + 1) {
1344  for (j = 0; j < height; j += 8) {
1345  for (i = 0; i < width; i += 8)
1346  if (process_block(ctx, dst + i, prev1 + i, prev2 + i, stride,
1347  tbl_pos + 8, 8))
1348  return AVERROR_INVALIDDATA;
1349  dst += stride * 8;
1350  prev1 += stride * 8;
1351  prev2 += stride * 8;
1352  }
1353  }
1354  break;
1355  case 3:
1356  memcpy(ctx->frm0, ctx->frm2, ctx->pitch * ctx->height);
1357  break;
1358  case 4:
1359  memcpy(ctx->frm0, ctx->frm1, ctx->pitch * ctx->height);
1360  break;
1361  case 5:
1362  if (rle_decode(ctx, &ctx->gb, dst, decoded_size))
1363  return AVERROR_INVALIDDATA;
1364  break;
1365  default:
1367  "Subcodec 47 compression %d", compr);
1368  return AVERROR_PATCHWELCOME;
1369  }
1370  if (seq == ctx->prev_seq + 1)
1371  ctx->rotate_code = new_rot;
1372  else
1373  ctx->rotate_code = 0;
1374  ctx->prev_seq = seq;
1375 
1376  return 0;
1377 }
1378 
1379 // scale 4x4 input block to an 8x8 output block
1380 static void c48_4to8(uint8_t *dst, const uint8_t *src, const uint16_t w)
1381 {
1382  uint16_t p;
1383  // dst is always at least 16bit aligned
1384  for (int i = 0; i < 4; i++) {
1385  for (int j = 0; j < 8; j += 2) {
1386  p = *src++;
1387  p = (p << 8) | p;
1388  *((uint16_t *)(dst + w * 0 + j)) = p;
1389  *((uint16_t *)(dst + w * 1 + j)) = p;
1390  }
1391  dst += w * 2;
1392  }
1393 }
1394 
1395 static int codec48_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *db,
1396  const uint16_t w)
1397 {
1398  uint8_t opc, sb[16];
1399  int i, j, k, l;
1400  int16_t mvofs;
1401  uint32_t ofs;
1402 
1403  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1404  return 1;
1405 
1406  opc = bytestream2_get_byteu(&ctx->gb);
1407  switch (opc) {
1408  case 0xFF: // 1x1 -> 8x8 block scale
1409  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1410  return 1;
1411 
1412  opc = bytestream2_get_byteu(&ctx->gb);
1413  for (i = 0; i < 16; i++)
1414  sb[i] = opc;
1415  c48_4to8(dst, sb, w);
1416  break;
1417  case 0xFE: // 1x 8x8 copy from deltabuf, 16bit mv from source
1418  if (bytestream2_get_bytes_left(&ctx->gb) < 2)
1419  return 1;
1420  mvofs = bytestream2_get_le16(&ctx->gb);
1421  for (i = 0; i < 8; i++) {
1422  ofs = w * i;
1423  for (k = 0; k < 8; k++)
1424  *(dst + ofs + k) = *(db + ofs + k + mvofs);
1425  }
1426  break;
1427  case 0xFD: // 2x2 -> 8x8 block scale
1428  if (bytestream2_get_bytes_left(&ctx->gb) < 4)
1429  return 1;
1430  sb[ 5] = bytestream2_get_byteu(&ctx->gb);
1431  sb[ 7] = bytestream2_get_byteu(&ctx->gb);
1432  sb[13] = bytestream2_get_byteu(&ctx->gb);
1433  sb[15] = bytestream2_get_byteu(&ctx->gb);
1434 
1435  sb[0] = sb[1] = sb[4] = sb[5];
1436  sb[2] = sb[3] = sb[6] = sb[7];
1437  sb[8] = sb[9] = sb[12] = sb[13];
1438  sb[10] = sb[11] = sb[14] = sb[15];
1439  c48_4to8(dst, sb, w);
1440  break;
1441  case 0xFC: // 4x copy 4x4 block, per-block c37_mv from source
1442  if (bytestream2_get_bytes_left(&ctx->gb) < 4)
1443  return 1;
1444  for (i = 0; i < 8; i += 4) {
1445  for (k = 0; k < 8; k += 4) {
1446  opc = bytestream2_get_byteu(&ctx->gb);
1447  mvofs = c37_mv[opc * 2] + (c37_mv[opc * 2 + 1] * w);
1448  for (j = 0; j < 4; j++) {
1449  ofs = (w * (j + i)) + k;
1450  for (l = 0; l < 4; l++)
1451  *(dst + ofs + l) = *(db + ofs + l + mvofs);
1452  }
1453  }
1454  }
1455  break;
1456  case 0xFB: // Copy 4x 4x4 blocks, per-block mv from source
1457  if (bytestream2_get_bytes_left(&ctx->gb) < 8)
1458  return 1;
1459  for (i = 0; i < 8; i += 4) {
1460  for (k = 0; k < 8; k += 4) {
1461  mvofs = bytestream2_get_le16(&ctx->gb);
1462  for (j = 0; j < 4; j++) {
1463  ofs = (w * (j + i)) + k;
1464  for (l = 0; l < 4; l++)
1465  *(dst + ofs + l) = *(db + ofs + l + mvofs);
1466  }
1467  }
1468  }
1469  break;
1470  case 0xFA: // scale 4x4 input block to 8x8 dest block
1471  if (bytestream2_get_bytes_left(&ctx->gb) < 16)
1472  return 1;
1473  bytestream2_get_bufferu(&ctx->gb, sb, 16);
1474  c48_4to8(dst, sb, w);
1475  break;
1476  case 0xF9: // 16x 2x2 copy from delta, per-block c37_mv from source
1477  if (bytestream2_get_bytes_left(&ctx->gb) < 16)
1478  return 1;
1479  for (i = 0; i < 8; i += 2) {
1480  for (j = 0; j < 8; j += 2) {
1481  ofs = (w * i) + j;
1482  opc = bytestream2_get_byteu(&ctx->gb);
1483  mvofs = c37_mv[opc * 2] + (c37_mv[opc * 2 + 1] * w);
1484  for (l = 0; l < 2; l++) {
1485  *(dst + ofs + l + 0) = *(db + ofs + l + 0 + mvofs);
1486  *(dst + ofs + l + w) = *(db + ofs + l + w + mvofs);
1487  }
1488  }
1489  }
1490  break;
1491  case 0xF8: // 16x 2x2 blocks copy, 16bit mv from source
1492  if (bytestream2_get_bytes_left(&ctx->gb) < 32)
1493  return 1;
1494  for (i = 0; i < 8; i += 2) {
1495  for (j = 0; j < 8; j += 2) {
1496  ofs = w * i + j;
1497  mvofs = bytestream2_get_le16(&ctx->gb);
1498  for (l = 0; l < 2; l++) {
1499  *(dst + ofs + l + 0) = *(db + ofs + l + 0 + mvofs);
1500  *(dst + ofs + l + w) = *(db + ofs + l + w + mvofs);
1501  }
1502  }
1503  }
1504  break;
1505  case 0xF7: // copy 8x8 block from src to dest
1506  if (bytestream2_get_bytes_left(&ctx->gb) < 64)
1507  return 1;
1508  for (i = 0; i < 8; i++) {
1509  ofs = i * w;
1510  for (l = 0; l < 8; l++)
1511  *(dst + ofs + l) = bytestream2_get_byteu(&ctx->gb);
1512  }
1513  break;
1514  default: // copy 8x8 block from prev, c37_mv from source
1515  mvofs = c37_mv[opc * 2] + (c37_mv[opc * 2 + 1] * w);
1516  for (i = 0; i < 8; i++) {
1517  ofs = i * w;
1518  for (l = 0; l < 8; l++)
1519  *(dst + ofs + l) = *(db + ofs + l + mvofs);
1520  }
1521  break;
1522  }
1523  return 0;
1524 }
1525 
1527 {
1528  uint8_t *dst, *prev;
1529  int compr = bytestream2_get_byte(&ctx->gb);
1530  int mvidx = bytestream2_get_byte(&ctx->gb);
1531  int seq = bytestream2_get_le16(&ctx->gb);
1532  uint32_t decoded_size = bytestream2_get_le32(&ctx->gb);
1533  int i, j, flags;
1534 
1535  // all codec48 videos use 1, but just to be safe...
1536  if (mvidx != 1) {
1537  av_log(ctx->avctx, AV_LOG_ERROR, "Invalid motion base value %d.\n", mvidx);
1538  return AVERROR_INVALIDDATA;
1539  }
1540 
1541  bytestream2_skip(&ctx->gb, 4);
1542  flags = bytestream2_get_byte(&ctx->gb);
1543  bytestream2_skip(&ctx->gb, 3);
1544 
1545  if (flags & 8) {
1546  if (bytestream2_get_bytes_left(&ctx->gb) < 0x8080)
1547  return AVERROR_INVALIDDATA;
1549  }
1550 
1551  dst = (uint8_t*)ctx->frm0;
1552  prev = (uint8_t*)ctx->frm2;
1553 
1554  if (!seq) {
1555  ctx->prev_seq = -1;
1556  memset(prev, 0, ctx->aligned_height * width);
1557  }
1558 
1559  switch (compr) {
1560  case 0:
1562  return AVERROR_INVALIDDATA;
1563  for (j = 0; j < height; j++) {
1565  dst += width;
1566  }
1567  break;
1568  case 2:
1569  if (rle_decode(ctx, &ctx->gb, dst, decoded_size))
1570  return AVERROR_INVALIDDATA;
1571  break;
1572  case 3:
1573  if (seq == ctx->prev_seq + 1) {
1574  for (j = 0; j < height; j += 8) {
1575  for (i = 0; i < width; i += 8) {
1576  if (codec48_block(ctx, dst + i, prev + i, width))
1577  return AVERROR_INVALIDDATA;
1578  }
1579  dst += width * 8;
1580  prev += width * 8;
1581  }
1582  }
1583  break;
1584  case 5:
1585  if (bytestream2_get_bytes_left(&ctx->gb) < ((width + 1) >> 1) * ((height + 1) >> 1))
1586  return AVERROR_INVALIDDATA;
1588  break;
1589 
1590  default:
1592  "Subcodec 48 compression %d", compr);
1593  return AVERROR_PATCHWELCOME;
1594  }
1595  ctx->rotate_code = 1; // swap frm[0] and frm[2]
1596  ctx->prev_seq = seq;
1597  return 0;
1598 }
1599 
1601 {
1602  uint16_t w, h, parm2;
1603  uint8_t codec, param;
1604  int16_t left, top;
1605 
1606  codec = bytestream2_get_byteu(gb);
1607  param = bytestream2_get_byteu(gb);
1608  left = bytestream2_get_le16u(gb);
1609  top = bytestream2_get_le16u(gb);
1610  w = bytestream2_get_le16u(gb);
1611  h = bytestream2_get_le16u(gb);
1612  bytestream2_skip(gb, 2);
1613  parm2 = bytestream2_get_le16u(gb);
1614 
1615  if (w < 1 || h < 1 || w > 800 || h > 600 || left > 800 || top > 600) {
1616  av_log(ctx->avctx, AV_LOG_WARNING,
1617  "ignoring invalid fobj dimensions: c%d %d %d @ %d %d\n",
1618  codec, w, h, left, top);
1619  return 0;
1620  }
1621 
1622  if (!ctx->have_dimensions) {
1623  int xres, yres;
1624  if (ctx->subversion < 2) {
1625  /* Rebel Assault 1: 384x242 internal size */
1626  xres = 384;
1627  yres = 242;
1628  ctx->have_dimensions = 1;
1629  } else if (codec == 37 || codec == 47 || codec == 48) {
1630  /* these codecs work on full frames, trust their dimensions */
1631  xres = w;
1632  yres = h;
1633  ctx->have_dimensions = 1;
1634  } else {
1635  /* Rebel Assault 2: 424x260 internal size */
1636  if (((left + w) == 424) && ((top + h) == 260))
1637  ctx->have_dimensions = 1;
1638 
1639  xres = FFMAX(left + w, ctx->width);
1640  yres = FFMAX(top + h, ctx->height);
1641  }
1642 
1643  if (ctx->width < xres || ctx->height < yres) {
1644  int ret = ff_set_dimensions(ctx->avctx, xres, yres);
1645  if (ret < 0)
1646  return ret;
1647  init_sizes(ctx, xres, yres);
1648  if (init_buffers(ctx)) {
1649  av_log(ctx->avctx, AV_LOG_ERROR, "Error resizing buffers.\n");
1650  return AVERROR(ENOMEM);
1651  }
1652  }
1653  } else {
1654  if (((left + w > ctx->width) || (top + h > ctx->height))
1655  && (codec >= 37)) {
1656  /* correct unexpected overly large frames: this happens
1657  * for instance with The Dig's sq1.san video: it has a few
1658  * (all black) 640x480 frames halfway in, while the rest is
1659  * 320x200.
1660  */
1661  av_log(ctx->avctx, AV_LOG_WARNING,
1662  "resizing too large fobj: c%d %d %d @ %d %d\n", codec, w, h, left, top);
1663  w = ctx->width;
1664  h = ctx->height;
1665  }
1666  }
1667 
1668  /* on first FOBJ, when the codec is not one of the
1669  * full-buffer codecs (37/47/48), frm0 needs to be cleared.
1670  */
1671  if (ctx->first_fob) {
1672  ctx->first_fob = 0;
1673  if (codec < 37)
1674  memset(ctx->frm0, 0, ctx->frm0_size);
1675  }
1676 
1677  switch (codec) {
1678  case 1:
1679  case 3:
1680  return old_codec1(ctx, gb, top, left, w, h, codec == 3);
1681  case 2:
1682  return old_codec2(ctx, gb, top, left, w, h);
1683  case 4:
1684  case 5:
1685  case 33:
1686  case 34:
1687  return old_codec4(ctx, gb, top, left, w, h, param, parm2, codec);
1688  case 20:
1689  return old_codec20(ctx, w, h);
1690  case 21:
1691  return old_codec21(ctx, gb, top, left, w, h);
1692  case 23:
1693  return old_codec23(ctx, gb, top, left, w, h, param, parm2);
1694  case 37:
1695  return old_codec37(ctx, w, h);
1696  case 45:
1697  return 0;
1698  case 47:
1699  return old_codec47(ctx, w, h);
1700  case 48:
1701  return old_codec48(ctx, w, h);
1702  default:
1703  avpriv_request_sample(ctx->avctx, "Subcodec %d", codec);
1704  ctx->frame->flags |= AV_FRAME_FLAG_CORRUPT;
1705  return 0;
1706  }
1707 }
1708 
1710 {
1711  uint8_t *sf = ctx->stored_frame;
1712  int xoff, yoff, left, top, ret;
1713  GetByteContext gb;
1714  uint32_t sz;
1715 
1716  /* FTCH defines additional x/y offsets */
1717  if (size != 12) {
1718  if (bytestream2_get_bytes_left(&ctx->gb) < 6)
1719  return AVERROR_INVALIDDATA;
1720  bytestream2_skip(&ctx->gb, 2);
1721  xoff = bytestream2_get_le16u(&ctx->gb);
1722  yoff = bytestream2_get_le16u(&ctx->gb);
1723  } else {
1724  if (bytestream2_get_bytes_left(&ctx->gb) < 12)
1725  return AVERROR_INVALIDDATA;
1726  bytestream2_skip(&ctx->gb, 4);
1727  xoff = bytestream2_get_be32u(&ctx->gb);
1728  yoff = bytestream2_get_be32u(&ctx->gb);
1729  }
1730 
1731  sz = *(uint32_t *)(sf + 0);
1732  if ((sz > 0) && (sz <= ctx->stored_frame_size - 4)) {
1733  /* add the FTCH offsets to the left/top values of the stored FOBJ */
1734  left = av_le2ne16(*(int16_t *)(sf + 4 + 2));
1735  top = av_le2ne16(*(int16_t *)(sf + 4 + 4));
1736  *(int16_t *)(sf + 4 + 2) = av_le2ne16(left + xoff);
1737  *(int16_t *)(sf + 4 + 4) = av_le2ne16(top + yoff);
1738 
1739  /* decode the stored FOBJ */
1740  bytestream2_init(&gb, sf + 4, sz);
1741  ret = process_frame_obj(ctx, &gb);
1742 
1743  /* now restore the original left/top values again */
1744  *(int16_t *)(sf + 4 + 2) = av_le2ne16(left);
1745  *(int16_t *)(sf + 4 + 4) = av_le2ne16(top);
1746  } else {
1747  /* this happens a lot in RA1: The individual files are meant to
1748  * be played in sequence, with some referencing objects STORed
1749  * by previous files, e.g. the cockpit codec21 object in RA1 LVL8.
1750  * But spamming the log with errors is also not helpful, so
1751  * here we simply ignore this case.
1752  */
1753  ret = 0;
1754  }
1755  return ret;
1756 }
1757 
1759 {
1760  int16_t *dp = ctx->delta_pal;
1761  uint32_t *pal = ctx->pal;
1762  uint16_t cmd;
1763  uint8_t c[3];
1764  int i, j;
1765 
1766  bytestream2_skip(&ctx->gb, 2);
1767  cmd = bytestream2_get_be16(&ctx->gb);
1768 
1769  if (cmd == 1) {
1770  for (i = 0; i < PALETTE_DELTA; i += 3) {
1771  c[0] = (*pal >> 16) & 0xFF;
1772  c[1] = (*pal >> 8) & 0xFF;
1773  c[2] = (*pal >> 0) & 0xFF;
1774  for (j = 0; j < 3; j++) {
1775  int cl = (c[j] * 129) + *dp++;
1776  c[j] = av_clip_uint8(cl / 128) & 0xFF;
1777  }
1778  *pal++ = 0xFFU << 24 | c[0] << 16 | c[1] << 8 | c[2];
1779  }
1780  } else if (cmd == 2) {
1781  if (size < PALETTE_DELTA * 2 + 4) {
1782  av_log(ctx->avctx, AV_LOG_ERROR,
1783  "Incorrect palette change block size %"PRIu32".\n", size);
1784  return AVERROR_INVALIDDATA;
1785  }
1786  for (i = 0; i < PALETTE_DELTA; i++)
1787  dp[i] = bytestream2_get_le16u(&ctx->gb);
1788 
1789  if (size >= PALETTE_DELTA * 2 + 4 + PALETTE_SIZE * 3) {
1790  for (i = 0; i < PALETTE_SIZE; i++)
1791  ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb);
1792  if (ctx->subversion < 2)
1793  ctx->pal[0] = 0xFFU << 24;
1794  }
1795  }
1796  return 0;
1797 }
1798 
1800 {
1801  uint16_t *frm = ctx->frm0;
1802  int x, y;
1803 
1804  if (bytestream2_get_bytes_left(&ctx->gb) < ctx->width * ctx->height * 2) {
1805  av_log(ctx->avctx, AV_LOG_ERROR, "Insufficient data for raw frame.\n");
1806  return AVERROR_INVALIDDATA;
1807  }
1808  for (y = 0; y < ctx->height; y++) {
1809  for (x = 0; x < ctx->width; x++)
1810  frm[x] = bytestream2_get_le16u(&ctx->gb);
1811  frm += ctx->pitch;
1812  }
1813  return 0;
1814 }
1815 
1817 {
1818  avpriv_request_sample(ctx->avctx, "Unknown/unsupported compression type");
1819  return AVERROR_PATCHWELCOME;
1820 }
1821 
1822 static void copy_block(uint16_t *pdest, uint16_t *psrc, int block_size, ptrdiff_t pitch)
1823 {
1824  uint8_t *dst = (uint8_t *)pdest;
1825  uint8_t *src = (uint8_t *)psrc;
1826  ptrdiff_t stride = pitch * 2;
1827 
1828  switch (block_size) {
1829  case 2:
1830  copy_block4(dst, src, stride, stride, 2);
1831  break;
1832  case 4:
1833  copy_block8(dst, src, stride, stride, 4);
1834  break;
1835  case 8:
1836  copy_block16(dst, src, stride, stride, 8);
1837  break;
1838  }
1839 }
1840 
1841 static void fill_block(uint16_t *pdest, uint16_t color, int block_size, ptrdiff_t pitch)
1842 {
1843  int x, y;
1844 
1845  pitch -= block_size;
1846  for (y = 0; y < block_size; y++, pdest += pitch)
1847  for (x = 0; x < block_size; x++)
1848  *pdest++ = color;
1849 }
1850 
1851 static int draw_glyph(SANMVideoContext *ctx, uint16_t *dst, int index,
1852  uint16_t fg_color, uint16_t bg_color, int block_size,
1853  ptrdiff_t pitch)
1854 {
1855  int8_t *pglyph;
1856  uint16_t colors[2] = { fg_color, bg_color };
1857  int x, y;
1858 
1859  if (index >= NGLYPHS) {
1860  av_log(ctx->avctx, AV_LOG_ERROR, "Ignoring nonexistent glyph #%u.\n", index);
1861  return AVERROR_INVALIDDATA;
1862  }
1863 
1864  pglyph = block_size == 8 ? ctx->p8x8glyphs[index] : ctx->p4x4glyphs[index];
1865  pitch -= block_size;
1866 
1867  for (y = 0; y < block_size; y++, dst += pitch)
1868  for (x = 0; x < block_size; x++)
1869  *dst++ = colors[*pglyph++];
1870  return 0;
1871 }
1872 
1873 static int opcode_0xf7(SANMVideoContext *ctx, int cx, int cy, int block_size, ptrdiff_t pitch)
1874 {
1875  uint16_t *dst = ctx->frm0 + cx + cy * ctx->pitch;
1876 
1877  if (block_size == 2) {
1878  uint32_t indices;
1879 
1880  if (bytestream2_get_bytes_left(&ctx->gb) < 4)
1881  return AVERROR_INVALIDDATA;
1882 
1883  indices = bytestream2_get_le32u(&ctx->gb);
1884  dst[0] = ctx->codebook[indices & 0xFF];
1885  indices >>= 8;
1886  dst[1] = ctx->codebook[indices & 0xFF];
1887  indices >>= 8;
1888  dst[pitch] = ctx->codebook[indices & 0xFF];
1889  indices >>= 8;
1890  dst[pitch + 1] = ctx->codebook[indices & 0xFF];
1891  } else {
1892  uint16_t fgcolor, bgcolor;
1893  int glyph;
1894 
1895  if (bytestream2_get_bytes_left(&ctx->gb) < 3)
1896  return AVERROR_INVALIDDATA;
1897 
1898  glyph = bytestream2_get_byteu(&ctx->gb);
1899  bgcolor = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
1900  fgcolor = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
1901 
1902  draw_glyph(ctx, dst, glyph, fgcolor, bgcolor, block_size, pitch);
1903  }
1904  return 0;
1905 }
1906 
1907 static int opcode_0xf8(SANMVideoContext *ctx, int cx, int cy, int block_size, ptrdiff_t pitch)
1908 {
1909  uint16_t *dst = ctx->frm0 + cx + cy * ctx->pitch;
1910 
1911  if (block_size == 2) {
1912  if (bytestream2_get_bytes_left(&ctx->gb) < 8)
1913  return AVERROR_INVALIDDATA;
1914 
1915  dst[0] = bytestream2_get_le16u(&ctx->gb);
1916  dst[1] = bytestream2_get_le16u(&ctx->gb);
1917  dst[pitch] = bytestream2_get_le16u(&ctx->gb);
1918  dst[pitch + 1] = bytestream2_get_le16u(&ctx->gb);
1919  } else {
1920  uint16_t fgcolor, bgcolor;
1921  int glyph;
1922 
1923  if (bytestream2_get_bytes_left(&ctx->gb) < 5)
1924  return AVERROR_INVALIDDATA;
1925 
1926  glyph = bytestream2_get_byteu(&ctx->gb);
1927  bgcolor = bytestream2_get_le16u(&ctx->gb);
1928  fgcolor = bytestream2_get_le16u(&ctx->gb);
1929 
1930  draw_glyph(ctx, dst, glyph, fgcolor, bgcolor, block_size, pitch);
1931  }
1932  return 0;
1933 }
1934 
1935 static int good_mvec(SANMVideoContext *ctx, int cx, int cy, int mx, int my,
1936  int block_size)
1937 {
1938  int start_pos = cx + mx + (cy + my) * ctx->pitch;
1939  int end_pos = start_pos + (block_size - 1) * (ctx->pitch + 1);
1940 
1941  int good = start_pos >= 0 && end_pos < (ctx->buf_size >> 1);
1942 
1943  if (!good)
1944  av_log(ctx->avctx, AV_LOG_ERROR,
1945  "Ignoring invalid motion vector (%i, %i)->(%u, %u), block size = %u\n",
1946  cx + mx, cy + my, cx, cy, block_size);
1947 
1948  return good;
1949 }
1950 
1951 static int codec2subblock(SANMVideoContext *ctx, int cx, int cy, int blk_size)
1952 {
1953  int16_t mx, my, index;
1954  int opcode;
1955 
1956  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1957  return AVERROR_INVALIDDATA;
1958 
1959  opcode = bytestream2_get_byteu(&ctx->gb);
1960 
1961  switch (opcode) {
1962  default:
1963  mx = motion_vectors[opcode][0];
1964  my = motion_vectors[opcode][1];
1965 
1966  if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
1967  copy_block(ctx->frm0 + cx + ctx->pitch * cy,
1968  ctx->frm2 + cx + mx + ctx->pitch * (cy + my),
1969  blk_size, ctx->pitch);
1970  }
1971  break;
1972  case 0xF5:
1973  if (bytestream2_get_bytes_left(&ctx->gb) < 2)
1974  return AVERROR_INVALIDDATA;
1975  index = bytestream2_get_le16u(&ctx->gb);
1976 
1977  mx = index % ctx->width;
1978  my = index / ctx->width;
1979 
1980  if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
1981  copy_block(ctx->frm0 + cx + ctx->pitch * cy,
1982  ctx->frm2 + cx + mx + ctx->pitch * (cy + my),
1983  blk_size, ctx->pitch);
1984  }
1985  break;
1986  case 0xF6:
1987  copy_block(ctx->frm0 + cx + ctx->pitch * cy,
1988  ctx->frm1 + cx + ctx->pitch * cy,
1989  blk_size, ctx->pitch);
1990  break;
1991  case 0xF7:
1992  opcode_0xf7(ctx, cx, cy, blk_size, ctx->pitch);
1993  break;
1994 
1995  case 0xF8:
1996  opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch);
1997  break;
1998  case 0xF9:
1999  case 0xFA:
2000  case 0xFB:
2001  case 0xFC:
2002  fill_block(ctx->frm0 + cx + cy * ctx->pitch,
2003  ctx->small_codebook[opcode - 0xf9], blk_size, ctx->pitch);
2004  break;
2005  case 0xFD:
2006  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
2007  return AVERROR_INVALIDDATA;
2008  fill_block(ctx->frm0 + cx + cy * ctx->pitch,
2009  ctx->codebook[bytestream2_get_byteu(&ctx->gb)], blk_size, ctx->pitch);
2010  break;
2011  case 0xFE:
2012  if (bytestream2_get_bytes_left(&ctx->gb) < 2)
2013  return AVERROR_INVALIDDATA;
2014  fill_block(ctx->frm0 + cx + cy * ctx->pitch,
2015  bytestream2_get_le16u(&ctx->gb), blk_size, ctx->pitch);
2016  break;
2017  case 0xFF:
2018  if (blk_size == 2) {
2019  opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch);
2020  } else {
2021  blk_size >>= 1;
2022  if (codec2subblock(ctx, cx, cy, blk_size))
2023  return AVERROR_INVALIDDATA;
2024  if (codec2subblock(ctx, cx + blk_size, cy, blk_size))
2025  return AVERROR_INVALIDDATA;
2026  if (codec2subblock(ctx, cx, cy + blk_size, blk_size))
2027  return AVERROR_INVALIDDATA;
2028  if (codec2subblock(ctx, cx + blk_size, cy + blk_size, blk_size))
2029  return AVERROR_INVALIDDATA;
2030  }
2031  break;
2032  }
2033  return 0;
2034 }
2035 
2037 {
2038  int cx, cy, ret;
2039 
2040  for (cy = 0; cy < ctx->aligned_height; cy += 8)
2041  for (cx = 0; cx < ctx->aligned_width; cx += 8)
2042  if (ret = codec2subblock(ctx, cx, cy, 8))
2043  return ret;
2044 
2045  return 0;
2046 }
2047 
2049 {
2050  memcpy(ctx->frm0, ctx->frm2, ctx->frm2_size);
2051  return 0;
2052 }
2053 
2055 {
2056  memcpy(ctx->frm0, ctx->frm1, ctx->frm1_size);
2057  return 0;
2058 }
2059 
2061 {
2062 #if HAVE_BIGENDIAN
2063  uint16_t *frm;
2064  int npixels;
2065 #endif
2066  uint8_t *dst = (uint8_t*)ctx->frm0;
2067 
2068  if (rle_decode(ctx, &ctx->gb, dst, ctx->buf_size))
2069  return AVERROR_INVALIDDATA;
2070 
2071 #if HAVE_BIGENDIAN
2072  npixels = ctx->npixels;
2073  frm = ctx->frm0;
2074  while (npixels--) {
2075  *frm = av_bswap16(*frm);
2076  frm++;
2077  }
2078 #endif
2079 
2080  return 0;
2081 }
2082 
2084 {
2085  int npixels = ctx->npixels;
2086  uint16_t *frm = ctx->frm0;
2087 
2088  if (bytestream2_get_bytes_left(&ctx->gb) < npixels) {
2089  av_log(ctx->avctx, AV_LOG_ERROR, "Insufficient data for frame.\n");
2090  return AVERROR_INVALIDDATA;
2091  }
2092  while (npixels--)
2093  *frm++ = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
2094 
2095  return 0;
2096 }
2097 
2099 {
2100  uint16_t *pdest = ctx->frm0;
2101  uint8_t *rsrc;
2102  long npixels = ctx->npixels;
2103 
2104  av_fast_malloc(&ctx->rle_buf, &ctx->rle_buf_size, npixels);
2105  if (!ctx->rle_buf) {
2106  av_log(ctx->avctx, AV_LOG_ERROR, "RLE buffer allocation failed.\n");
2107  return AVERROR(ENOMEM);
2108  }
2109  rsrc = ctx->rle_buf;
2110 
2111  if (rle_decode(ctx, &ctx->gb, rsrc, npixels))
2112  return AVERROR_INVALIDDATA;
2113 
2114  while (npixels--)
2115  *pdest++ = ctx->codebook[*rsrc++];
2116 
2117  return 0;
2118 }
2119 
2121 
2122 static const frm_decoder v1_decoders[] = {
2125 };
2126 
2128 {
2129  int i, ret;
2130 
2131  if ((ret = bytestream2_get_bytes_left(&ctx->gb)) < 560) {
2132  av_log(ctx->avctx, AV_LOG_ERROR, "Input frame too short (%d bytes).\n",
2133  ret);
2134  return AVERROR_INVALIDDATA;
2135  }
2136  bytestream2_skip(&ctx->gb, 8); // skip pad
2137 
2138  hdr->width = bytestream2_get_le32u(&ctx->gb);
2139  hdr->height = bytestream2_get_le32u(&ctx->gb);
2140 
2141  if (hdr->width != ctx->width || hdr->height != ctx->height) {
2142  avpriv_report_missing_feature(ctx->avctx, "Variable size frames");
2143  return AVERROR_PATCHWELCOME;
2144  }
2145 
2146  hdr->seq_num = bytestream2_get_le16u(&ctx->gb);
2147  hdr->codec = bytestream2_get_byteu(&ctx->gb);
2148  hdr->rotate_code = bytestream2_get_byteu(&ctx->gb);
2149 
2150  bytestream2_skip(&ctx->gb, 4); // skip pad
2151 
2152  for (i = 0; i < 4; i++)
2153  ctx->small_codebook[i] = bytestream2_get_le16u(&ctx->gb);
2154  hdr->bg_color = bytestream2_get_le16u(&ctx->gb);
2155 
2156  bytestream2_skip(&ctx->gb, 2); // skip pad
2157 
2158  hdr->rle_output_size = bytestream2_get_le32u(&ctx->gb);
2159  for (i = 0; i < 256; i++)
2160  ctx->codebook[i] = bytestream2_get_le16u(&ctx->gb);
2161 
2162  bytestream2_skip(&ctx->gb, 8); // skip pad
2163 
2164  return 0;
2165 }
2166 
2167 static void fill_frame(uint16_t *pbuf, int buf_size, uint16_t color)
2168 {
2169  if (buf_size--) {
2170  *pbuf++ = color;
2171  av_memcpy_backptr((uint8_t*)pbuf, 2, 2*buf_size);
2172  }
2173 }
2174 
2176 {
2177  uint8_t *dst;
2178  const uint8_t *src = (uint8_t*) ctx->frm0;
2179  int ret, height = ctx->height;
2180  ptrdiff_t dstpitch, srcpitch = ctx->pitch * (hdr ? sizeof(ctx->frm0[0]) : 1);
2181 
2182  if ((ret = ff_get_buffer(ctx->avctx, ctx->frame, 0)) < 0)
2183  return ret;
2184 
2185  dst = ctx->frame->data[0];
2186  dstpitch = ctx->frame->linesize[0];
2187 
2188  while (height--) {
2189  memcpy(dst, src, srcpitch);
2190  src += srcpitch;
2191  dst += dstpitch;
2192  }
2193 
2194  return 0;
2195 }
2196 
2198  int *got_frame_ptr, AVPacket *pkt)
2199 {
2200  SANMVideoContext *ctx = avctx->priv_data;
2201  int i, ret;
2202 
2203  ctx->frame = frame;
2204  bytestream2_init(&ctx->gb, pkt->data, pkt->size);
2205 
2206  if (!ctx->version) {
2207  int to_store = 0, have_img = 0;
2208 
2209  ctx->first_fob = 1;
2210 
2211  while (bytestream2_get_bytes_left(&ctx->gb) >= 8) {
2212  uint32_t sig, size;
2213  int pos;
2214 
2215  sig = bytestream2_get_be32u(&ctx->gb);
2216  size = bytestream2_get_be32u(&ctx->gb);
2217  pos = bytestream2_tell(&ctx->gb);
2218 
2219  if (bytestream2_get_bytes_left(&ctx->gb) < size) {
2220  av_log(avctx, AV_LOG_ERROR, "Incorrect chunk size %"PRIu32".\n", size);
2221  break;
2222  }
2223  switch (sig) {
2224  case MKBETAG('N', 'P', 'A', 'L'):
2225  if (size != PALETTE_SIZE * 3) {
2226  av_log(avctx, AV_LOG_ERROR,
2227  "Incorrect palette block size %"PRIu32".\n", size);
2228  return AVERROR_INVALIDDATA;
2229  }
2230  for (i = 0; i < PALETTE_SIZE; i++)
2231  ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb);
2232  if (ctx->subversion < 2)
2233  ctx->pal[0] = 0xFFU << 24;
2234  break;
2235  case MKBETAG('F', 'O', 'B', 'J'):
2236  if (size < 16)
2237  return AVERROR_INVALIDDATA;
2238  if (ret = process_frame_obj(ctx, &ctx->gb))
2239  return ret;
2240  have_img = 1;
2241 
2242  /* STOR: for ANIMv0/1 store the whole FOBJ datablock, as it
2243  * needs to be replayed on FTCH, since none of the codecs
2244  * it uses work on the full buffer.
2245  * For ANIMv2, it's enough to store the current framebuffer.
2246  */
2247  if (to_store) {
2248  to_store = 0;
2249  if (ctx->subversion < 2) {
2250  if (size + 4 <= ctx->stored_frame_size) {
2251  int pos2 = bytestream2_tell(&ctx->gb);
2252  bytestream2_seek(&ctx->gb, pos, SEEK_SET);
2253  *(uint32_t *)(ctx->stored_frame) = size;
2254  bytestream2_get_bufferu(&ctx->gb, ctx->stored_frame + 4, size);
2255  bytestream2_seek(&ctx->gb, pos2, SEEK_SET);
2256  } else {
2257  av_log(avctx, AV_LOG_ERROR, "FOBJ too large for STOR\n");
2258  ret = AVERROR(ENOMEM);
2259  }
2260  } else {
2261  memcpy(ctx->stored_frame, ctx->frm0, ctx->buf_size);
2262  }
2263  }
2264  break;
2265  case MKBETAG('X', 'P', 'A', 'L'):
2266  if (ret = process_xpal(ctx, size))
2267  return ret;
2268  break;
2269  case MKBETAG('S', 'T', 'O', 'R'):
2270  to_store = 1;
2271  break;
2272  case MKBETAG('F', 'T', 'C', 'H'):
2273  if (ctx->subversion < 2) {
2274  if (ret = process_ftch(ctx, size))
2275  return ret;
2276  } else {
2277  memcpy(ctx->frm0, ctx->stored_frame, ctx->buf_size);
2278  }
2279  have_img = 1;
2280  break;
2281  default:
2282  bytestream2_skip(&ctx->gb, size);
2283  av_log(avctx, AV_LOG_DEBUG,
2284  "Unknown/unsupported chunk %"PRIx32".\n", sig);
2285  break;
2286  }
2287 
2288  /* the sizes of chunks are usually a multiple of 2. However
2289  * there are a few unaligned FOBJs in RA1 L2PLAY.ANM only (looks
2290  * like a game bug) and IACT audio chunks which have odd sizes
2291  * but are padded with a zero byte.
2292  */
2293  bytestream2_seek(&ctx->gb, pos + size, SEEK_SET);
2294  if ((pos + size) & 1) {
2295  if (0 != bytestream2_get_byteu(&ctx->gb))
2296  bytestream2_seek(&ctx->gb, pos + size, SEEK_SET);
2297  }
2298  }
2299 
2300  if (have_img) {
2301  if ((ret = copy_output(ctx, NULL)))
2302  return ret;
2303  memcpy(ctx->frame->data[1], ctx->pal, 1024);
2304  *got_frame_ptr = 1;
2305  }
2306  } else {
2308 
2309  if ((ret = read_frame_header(ctx, &header)))
2310  return ret;
2311 
2312  ctx->rotate_code = header.rotate_code;
2313  if (!header.seq_num) {
2314  ctx->frame->flags |= AV_FRAME_FLAG_KEY;
2315  ctx->frame->pict_type = AV_PICTURE_TYPE_I;
2316  fill_frame(ctx->frm1, ctx->npixels, header.bg_color);
2317  fill_frame(ctx->frm2, ctx->npixels, header.bg_color);
2318  } else {
2319  ctx->frame->flags &= ~AV_FRAME_FLAG_KEY;
2320  ctx->frame->pict_type = AV_PICTURE_TYPE_P;
2321  }
2322 
2323  if (header.codec < FF_ARRAY_ELEMS(v1_decoders)) {
2324  if ((ret = v1_decoders[header.codec](ctx))) {
2325  av_log(avctx, AV_LOG_ERROR,
2326  "Subcodec %d: error decoding frame.\n", header.codec);
2327  return ret;
2328  }
2329  } else {
2330  avpriv_request_sample(avctx, "Subcodec %d", header.codec);
2331  return AVERROR_PATCHWELCOME;
2332  }
2333 
2334  if ((ret = copy_output(ctx, &header)))
2335  return ret;
2336 
2337  *got_frame_ptr = 1;
2338 
2339  }
2340  if (ctx->rotate_code)
2341  rotate_bufs(ctx, ctx->rotate_code);
2342 
2343  return pkt->size;
2344 }
2345 
2347  .p.name = "sanm",
2348  CODEC_LONG_NAME("LucasArts SANM/Smush video"),
2349  .p.type = AVMEDIA_TYPE_VIDEO,
2350  .p.id = AV_CODEC_ID_SANM,
2351  .priv_data_size = sizeof(SANMVideoContext),
2352  .init = decode_init,
2353  .close = decode_end,
2355  .p.capabilities = AV_CODEC_CAP_DR1,
2356 };
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:757
codec47_read_interptable
static void codec47_read_interptable(SANMVideoContext *ctx)
Definition: sanm.c:1242
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:215
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
old_codec20
static int old_codec20(SANMVideoContext *ctx, int w, int h)
Definition: sanm.c:950
decode_0
static int decode_0(SANMVideoContext *ctx)
Definition: sanm.c:1799
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:2060
fill_block
static void fill_block(uint16_t *pdest, uint16_t color, int block_size, ptrdiff_t pitch)
Definition: sanm.c:1841
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
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:1152
GetByteContext
Definition: bytestream.h:33
SANMVideoContext::pal
uint32_t pal[PALETTE_SIZE]
Definition: sanm.c:268
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
SANMVideoContext::frm0
uint16_t * frm0
Definition: sanm.c:277
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:1935
mask
int mask
Definition: mediacodecdec_common.c:154
out_size
int out_size
Definition: movenc.c:56
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:410
w
uint8_t w
Definition: llviddspenc.c:38
AVPacket::data
uint8_t * data
Definition: packet.h:535
decode_end
static av_cold int decode_end(AVCodecContext *avctx)
Definition: sanm.c:663
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:2048
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:2346
bit
#define bit(string, value)
Definition: cbs_mpeg2.c:56
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:53
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:2036
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:209
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:625
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:1395
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:2083
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1416
c48_4to8
static void c48_4to8(uint8_t *dst, const uint8_t *src, const uint16_t w)
Definition: sanm.c:1380
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:932
codec47_comp1
static void codec47_comp1(SANMVideoContext *ctx, uint8_t *dst_in, int width, int height, ptrdiff_t stride)
Definition: sanm.c:1258
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:230
opcode_0xf8
static int opcode_0xf8(SANMVideoContext *ctx, int cx, int cy, int block_size, ptrdiff_t pitch)
Definition: sanm.c:1907
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:53
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:1291
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:204
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:783
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:1851
AV_PICTURE_TYPE_I
@ AV_PICTURE_TYPE_I
Intra.
Definition: avutil.h:279
decode_nop
static int decode_nop(SANMVideoContext *ctx)
Definition: sanm.c:1816
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:619
process_frame_obj
static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb)
Definition: sanm.c:1600
close
av_cold void CBS_FUNC() close(CodedBitstreamContext **ctx_ptr)
Close a context and free all internal state.
Definition: cbs.c:140
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:552
bytestream2_get_bytes_left
static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:158
bytestream2_tell
static av_always_inline int bytestream2_tell(GetByteContext *g)
Definition: bytestream.h:192
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:1611
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:536
SANMVideoContext
Definition: sanm.c:263
height
#define height
Definition: dsp.h:85
codec37_mv
static void codec37_mv(uint8_t *dst, const uint8_t *src, int height, int stride, int x, int y)
Definition: sanm.c:968
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:83
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:424
decode_4
static int decode_4(SANMVideoContext *ctx)
Definition: sanm.c:2054
size
int size
Definition: twinvq_data.h:10344
color
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:96
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
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:672
decode_init
static av_cold int decode_init(AVCodecContext *avctx)
Definition: sanm.c:626
old_codec37
static int old_codec37(SANMVideoContext *ctx, int width, int height)
Definition: sanm.c:987
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:67
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:621
fill_frame
static void fill_frame(uint16_t *pbuf, int buf_size, uint16_t color)
Definition: sanm.c:2167
copy_block.h
copy_block
static void copy_block(uint16_t *pdest, uint16_t *psrc, int block_size, ptrdiff_t pitch)
Definition: sanm.c:1822
AVCodecContext::extradata
uint8_t * extradata
Out-of-band global headers that may be used by some codecs.
Definition: avcodec.h:514
process_xpal
static int process_xpal(SANMVideoContext *ctx, int size)
Definition: sanm.c:1758
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::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:515
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:2127
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:264
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:839
AVCodecContext
main external API structure.
Definition: avcodec.h:431
copy_output
static int copy_output(SANMVideoContext *ctx, SANMFrameHeader *hdr)
Definition: sanm.c:2175
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:1526
codec4_load_tiles
static int codec4_load_tiles(SANMVideoContext *ctx, GetByteContext *gb, uint16_t param2, uint8_t clr)
Definition: sanm.c:601
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:280
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
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:1873
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AVPacket
This structure stores compressed data.
Definition: packet.h:512
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:485
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:1951
frm_decoder
int(* frm_decoder)(SANMVideoContext *ctx)
Definition: sanm.c:2120
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:2122
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:1709
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:882
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:85
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:375
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:2098
decode_frame
static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *pkt)
Definition: sanm.c:2197
init_buffers
static av_cold int init_buffers(SANMVideoContext *ctx)
Definition: sanm.c:467