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