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