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