Thanks to visit codestin.com
Credit goes to www.ffmpeg.org

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 /* codec47/bl16 motion vectors */
54 static const int8_t c47_mv[256][2] = {
55  { 0, 0 }, { -1, -43 }, { 6, -43 }, { -9, -42 }, { 13, -41 },
56  { -16, -40 }, { 19, -39 }, { -23, -36 }, { 26, -34 }, { -2, -33 },
57  { 4, -33 }, { -29, -32 }, { -9, -32 }, { 11, -31 }, { -16, -29 },
58  { 32, -29 }, { 18, -28 }, { -34, -26 }, { -22, -25 }, { -1, -25 },
59  { 3, -25 }, { -7, -24 }, { 8, -24 }, { 24, -23 }, { 36, -23 },
60  { -12, -22 }, { 13, -21 }, { -38, -20 }, { 0, -20 }, { -27, -19 },
61  { -4, -19 }, { 4, -19 }, { -17, -18 }, { -8, -17 }, { 8, -17 },
62  { 18, -17 }, { 28, -17 }, { 39, -17 }, { -12, -15 }, { 12, -15 },
63  { -21, -14 }, { -1, -14 }, { 1, -14 }, { -41, -13 }, { -5, -13 },
64  { 5, -13 }, { 21, -13 }, { -31, -12 }, { -15, -11 }, { -8, -11 },
65  { 8, -11 }, { 15, -11 }, { -2, -10 }, { 1, -10 }, { 31, -10 },
66  { -23, -9 }, { -11, -9 }, { -5, -9 }, { 4, -9 }, { 11, -9 },
67  { 42, -9 }, { 6, -8 }, { 24, -8 }, { -18, -7 }, { -7, -7 },
68  { -3, -7 }, { -1, -7 }, { 2, -7 }, { 18, -7 }, { -43, -6 },
69  { -13, -6 }, { -4, -6 }, { 4, -6 }, { 8, -6 }, { -33, -5 },
70  { -9, -5 }, { -2, -5 }, { 0, -5 }, { 2, -5 }, { 5, -5 },
71  { 13, -5 }, { -25, -4 }, { -6, -4 }, { -3, -4 }, { 3, -4 },
72  { 9, -4 }, { -19, -3 }, { -7, -3 }, { -4, -3 }, { -2, -3 },
73  { -1, -3 }, { 0, -3 }, { 1, -3 }, { 2, -3 }, { 4, -3 },
74  { 6, -3 }, { 33, -3 }, { -14, -2 }, { -10, -2 }, { -5, -2 },
75  { -3, -2 }, { -2, -2 }, { -1, -2 }, { 0, -2 }, { 1, -2 },
76  { 2, -2 }, { 3, -2 }, { 5, -2 }, { 7, -2 }, { 14, -2 },
77  { 19, -2 }, { 25, -2 }, { 43, -2 }, { -7, -1 }, { -3, -1 },
78  { -2, -1 }, { -1, -1 }, { 0, -1 }, { 1, -1 }, { 2, -1 },
79  { 3, -1 }, { 10, -1 }, { -5, 0 }, { -3, 0 }, { -2, 0 },
80  { -1, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 }, { 5, 0 },
81  { 7, 0 }, { -10, 1 }, { -7, 1 }, { -3, 1 }, { -2, 1 },
82  { -1, 1 }, { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 },
83  { -43, 2 }, { -25, 2 }, { -19, 2 }, { -14, 2 }, { -5, 2 },
84  { -3, 2 }, { -2, 2 }, { -1, 2 }, { 0, 2 }, { 1, 2 },
85  { 2, 2 }, { 3, 2 }, { 5, 2 }, { 7, 2 }, { 10, 2 },
86  { 14, 2 }, { -33, 3 }, { -6, 3 }, { -4, 3 }, { -2, 3 },
87  { -1, 3 }, { 0, 3 }, { 1, 3 }, { 2, 3 }, { 4, 3 },
88  { 19, 3 }, { -9, 4 }, { -3, 4 }, { 3, 4 }, { 7, 4 },
89  { 25, 4 }, { -13, 5 }, { -5, 5 }, { -2, 5 }, { 0, 5 },
90  { 2, 5 }, { 5, 5 }, { 9, 5 }, { 33, 5 }, { -8, 6 },
91  { -4, 6 }, { 4, 6 }, { 13, 6 }, { 43, 6 }, { -18, 7 },
92  { -2, 7 }, { 0, 7 }, { 2, 7 }, { 7, 7 }, { 18, 7 },
93  { -24, 8 }, { -6, 8 }, { -42, 9 }, { -11, 9 }, { -4, 9 },
94  { 5, 9 }, { 11, 9 }, { 23, 9 }, { -31, 10 }, { -1, 10 },
95  { 2, 10 }, { -15, 11 }, { -8, 11 }, { 8, 11 }, { 15, 11 },
96  { 31, 12 }, { -21, 13 }, { -5, 13 }, { 5, 13 }, { 41, 13 },
97  { -1, 14 }, { 1, 14 }, { 21, 14 }, { -12, 15 }, { 12, 15 },
98  { -39, 17 }, { -28, 17 }, { -18, 17 }, { -8, 17 }, { 8, 17 },
99  { 17, 18 }, { -4, 19 }, { 0, 19 }, { 4, 19 }, { 27, 19 },
100  { 38, 20 }, { -13, 21 }, { 12, 22 }, { -36, 23 }, { -24, 23 },
101  { -8, 24 }, { 7, 24 }, { -3, 25 }, { 1, 25 }, { 22, 25 },
102  { 34, 26 }, { -18, 28 }, { -32, 29 }, { 16, 29 }, { -11, 31 },
103  { 9, 32 }, { 29, 32 }, { -4, 33 }, { 2, 33 }, { -26, 34 },
104  { 23, 36 }, { -19, 39 }, { 16, 40 }, { -13, 41 }, { 9, 42 },
105  { -6, 43 }, { 1, 43 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
106 };
107 
108 /* codec37/48 motion vector tables: 3x 512 bytes/256 x-y pairs */
109 static const int8_t c37_mv[] = {
110  0, 0, 1, 0, 2, 0, 3, 0, 5, 0,
111  8, 0, 13, 0, 21, 0, -1, 0, -2, 0,
112  -3, 0, -5, 0, -8, 0, -13, 0, -17, 0,
113  -21, 0, 0, 1, 1, 1, 2, 1, 3, 1,
114  5, 1, 8, 1, 13, 1, 21, 1, -1, 1,
115  -2, 1, -3, 1, -5, 1, -8, 1, -13, 1,
116  -17, 1, -21, 1, 0, 2, 1, 2, 2, 2,
117  3, 2, 5, 2, 8, 2, 13, 2, 21, 2,
118  -1, 2, -2, 2, -3, 2, -5, 2, -8, 2,
119  -13, 2, -17, 2, -21, 2, 0, 3, 1, 3,
120  2, 3, 3, 3, 5, 3, 8, 3, 13, 3,
121  21, 3, -1, 3, -2, 3, -3, 3, -5, 3,
122  -8, 3, -13, 3, -17, 3, -21, 3, 0, 5,
123  1, 5, 2, 5, 3, 5, 5, 5, 8, 5,
124  13, 5, 21, 5, -1, 5, -2, 5, -3, 5,
125  -5, 5, -8, 5, -13, 5, -17, 5, -21, 5,
126  0, 8, 1, 8, 2, 8, 3, 8, 5, 8,
127  8, 8, 13, 8, 21, 8, -1, 8, -2, 8,
128  -3, 8, -5, 8, -8, 8, -13, 8, -17, 8,
129  -21, 8, 0, 13, 1, 13, 2, 13, 3, 13,
130  5, 13, 8, 13, 13, 13, 21, 13, -1, 13,
131  -2, 13, -3, 13, -5, 13, -8, 13, -13, 13,
132  -17, 13, -21, 13, 0, 21, 1, 21, 2, 21,
133  3, 21, 5, 21, 8, 21, 13, 21, 21, 21,
134  -1, 21, -2, 21, -3, 21, -5, 21, -8, 21,
135  -13, 21, -17, 21, -21, 21, 0, -1, 1, -1,
136  2, -1, 3, -1, 5, -1, 8, -1, 13, -1,
137  21, -1, -1, -1, -2, -1, -3, -1, -5, -1,
138  -8, -1, -13, -1, -17, -1, -21, -1, 0, -2,
139  1, -2, 2, -2, 3, -2, 5, -2, 8, -2,
140  13, -2, 21, -2, -1, -2, -2, -2, -3, -2,
141  -5, -2, -8, -2, -13, -2, -17, -2, -21, -2,
142  0, -3, 1, -3, 2, -3, 3, -3, 5, -3,
143  8, -3, 13, -3, 21, -3, -1, -3, -2, -3,
144  -3, -3, -5, -3, -8, -3, -13, -3, -17, -3,
145  -21, -3, 0, -5, 1, -5, 2, -5, 3, -5,
146  5, -5, 8, -5, 13, -5, 21, -5, -1, -5,
147  -2, -5, -3, -5, -5, -5, -8, -5, -13, -5,
148  -17, -5, -21, -5, 0, -8, 1, -8, 2, -8,
149  3, -8, 5, -8, 8, -8, 13, -8, 21, -8,
150  -1, -8, -2, -8, -3, -8, -5, -8, -8, -8,
151  -13, -8, -17, -8, -21, -8, 0, -13, 1, -13,
152  2, -13, 3, -13, 5, -13, 8, -13, 13, -13,
153  21, -13, -1, -13, -2, -13, -3, -13, -5, -13,
154  -8, -13, -13, -13, -17, -13, -21, -13, 0, -17,
155  1, -17, 2, -17, 3, -17, 5, -17, 8, -17,
156  13, -17, 21, -17, -1, -17, -2, -17, -3, -17,
157  -5, -17, -8, -17, -13, -17, -17, -17, -21, -17,
158  0, -21, 1, -21, 2, -21, 3, -21, 5, -21,
159  8, -21, 13, -21, 21, -21, -1, -21, -2, -21,
160  -3, -21, -5, -21, -8, -21, -13, -21, -17, -21,
161  0, 0,
162  0, 0, -8, -29, 8, -29, -18, -25, 17, -25,
163  0, -23, -6, -22, 6, -22, -13, -19, 12, -19,
164  0, -18, 25, -18, -25, -17, -5, -17, 5, -17,
165  -10, -15, 10, -15, 0, -14, -4, -13, 4, -13,
166  19, -13, -19, -12, -8, -11, -2, -11, 0, -11,
167  2, -11, 8, -11, -15, -10, -4, -10, 4, -10,
168  15, -10, -6, -9, -1, -9, 1, -9, 6, -9,
169  -29, -8, -11, -8, -8, -8, -3, -8, 3, -8,
170  8, -8, 11, -8, 29, -8, -5, -7, -2, -7,
171  0, -7, 2, -7, 5, -7, -22, -6, -9, -6,
172  -6, -6, -3, -6, -1, -6, 1, -6, 3, -6,
173  6, -6, 9, -6, 22, -6, -17, -5, -7, -5,
174  -4, -5, -2, -5, 0, -5, 2, -5, 4, -5,
175  7, -5, 17, -5, -13, -4, -10, -4, -5, -4,
176  -3, -4, -1, -4, 0, -4, 1, -4, 3, -4,
177  5, -4, 10, -4, 13, -4, -8, -3, -6, -3,
178  -4, -3, -3, -3, -2, -3, -1, -3, 0, -3,
179  1, -3, 2, -3, 4, -3, 6, -3, 8, -3,
180  -11, -2, -7, -2, -5, -2, -3, -2, -2, -2,
181  -1, -2, 0, -2, 1, -2, 2, -2, 3, -2,
182  5, -2, 7, -2, 11, -2, -9, -1, -6, -1,
183  -4, -1, -3, -1, -2, -1, -1, -1, 0, -1,
184  1, -1, 2, -1, 3, -1, 4, -1, 6, -1,
185  9, -1, -31, 0, -23, 0, -18, 0, -14, 0,
186  -11, 0, -7, 0, -5, 0, -4, 0, -3, 0,
187  -2, 0, -1, 0, 0, -31, 1, 0, 2, 0,
188  3, 0, 4, 0, 5, 0, 7, 0, 11, 0,
189  14, 0, 18, 0, 23, 0, 31, 0, -9, 1,
190  -6, 1, -4, 1, -3, 1, -2, 1, -1, 1,
191  0, 1, 1, 1, 2, 1, 3, 1, 4, 1,
192  6, 1, 9, 1, -11, 2, -7, 2, -5, 2,
193  -3, 2, -2, 2, -1, 2, 0, 2, 1, 2,
194  2, 2, 3, 2, 5, 2, 7, 2, 11, 2,
195  -8, 3, -6, 3, -4, 3, -2, 3, -1, 3,
196  0, 3, 1, 3, 2, 3, 3, 3, 4, 3,
197  6, 3, 8, 3, -13, 4, -10, 4, -5, 4,
198  -3, 4, -1, 4, 0, 4, 1, 4, 3, 4,
199  5, 4, 10, 4, 13, 4, -17, 5, -7, 5,
200  -4, 5, -2, 5, 0, 5, 2, 5, 4, 5,
201  7, 5, 17, 5, -22, 6, -9, 6, -6, 6,
202  -3, 6, -1, 6, 1, 6, 3, 6, 6, 6,
203  9, 6, 22, 6, -5, 7, -2, 7, 0, 7,
204  2, 7, 5, 7, -29, 8, -11, 8, -8, 8,
205  -3, 8, 3, 8, 8, 8, 11, 8, 29, 8,
206  -6, 9, -1, 9, 1, 9, 6, 9, -15, 10,
207  -4, 10, 4, 10, 15, 10, -8, 11, -2, 11,
208  0, 11, 2, 11, 8, 11, 19, 12, -19, 13,
209  -4, 13, 4, 13, 0, 14, -10, 15, 10, 15,
210  -5, 17, 5, 17, 25, 17, -25, 18, 0, 18,
211  -12, 19, 13, 19, -6, 22, 6, 22, 0, 23,
212  -17, 25, 18, 25, -8, 29, 8, 29, 0, 31,
213  0, 0,
214  0, 0, -6, -22, 6, -22, -13, -19, 12, -19,
215  0, -18, -5, -17, 5, -17, -10, -15, 10, -15,
216  0, -14, -4, -13, 4, -13, 19, -13, -19, -12,
217  -8, -11, -2, -11, 0, -11, 2, -11, 8, -11,
218  -15, -10, -4, -10, 4, -10, 15, -10, -6, -9,
219  -1, -9, 1, -9, 6, -9, -11, -8, -8, -8,
220  -3, -8, 0, -8, 3, -8, 8, -8, 11, -8,
221  -5, -7, -2, -7, 0, -7, 2, -7, 5, -7,
222  -22, -6, -9, -6, -6, -6, -3, -6, -1, -6,
223  1, -6, 3, -6, 6, -6, 9, -6, 22, -6,
224  -17, -5, -7, -5, -4, -5, -2, -5, -1, -5,
225  0, -5, 1, -5, 2, -5, 4, -5, 7, -5,
226  17, -5, -13, -4, -10, -4, -5, -4, -3, -4,
227  -2, -4, -1, -4, 0, -4, 1, -4, 2, -4,
228  3, -4, 5, -4, 10, -4, 13, -4, -8, -3,
229  -6, -3, -4, -3, -3, -3, -2, -3, -1, -3,
230  0, -3, 1, -3, 2, -3, 3, -3, 4, -3,
231  6, -3, 8, -3, -11, -2, -7, -2, -5, -2,
232  -4, -2, -3, -2, -2, -2, -1, -2, 0, -2,
233  1, -2, 2, -2, 3, -2, 4, -2, 5, -2,
234  7, -2, 11, -2, -9, -1, -6, -1, -5, -1,
235  -4, -1, -3, -1, -2, -1, -1, -1, 0, -1,
236  1, -1, 2, -1, 3, -1, 4, -1, 5, -1,
237  6, -1, 9, -1, -23, 0, -18, 0, -14, 0,
238  -11, 0, -7, 0, -5, 0, -4, 0, -3, 0,
239  -2, 0, -1, 0, 0, -23, 1, 0, 2, 0,
240  3, 0, 4, 0, 5, 0, 7, 0, 11, 0,
241  14, 0, 18, 0, 23, 0, -9, 1, -6, 1,
242  -5, 1, -4, 1, -3, 1, -2, 1, -1, 1,
243  0, 1, 1, 1, 2, 1, 3, 1, 4, 1,
244  5, 1, 6, 1, 9, 1, -11, 2, -7, 2,
245  -5, 2, -4, 2, -3, 2, -2, 2, -1, 2,
246  0, 2, 1, 2, 2, 2, 3, 2, 4, 2,
247  5, 2, 7, 2, 11, 2, -8, 3, -6, 3,
248  -4, 3, -3, 3, -2, 3, -1, 3, 0, 3,
249  1, 3, 2, 3, 3, 3, 4, 3, 6, 3,
250  8, 3, -13, 4, -10, 4, -5, 4, -3, 4,
251  -2, 4, -1, 4, 0, 4, 1, 4, 2, 4,
252  3, 4, 5, 4, 10, 4, 13, 4, -17, 5,
253  -7, 5, -4, 5, -2, 5, -1, 5, 0, 5,
254  1, 5, 2, 5, 4, 5, 7, 5, 17, 5,
255  -22, 6, -9, 6, -6, 6, -3, 6, -1, 6,
256  1, 6, 3, 6, 6, 6, 9, 6, 22, 6,
257  -5, 7, -2, 7, 0, 7, 2, 7, 5, 7,
258  -11, 8, -8, 8, -3, 8, 0, 8, 3, 8,
259  8, 8, 11, 8, -6, 9, -1, 9, 1, 9,
260  6, 9, -15, 10, -4, 10, 4, 10, 15, 10,
261  -8, 11, -2, 11, 0, 11, 2, 11, 8, 11,
262  19, 12, -19, 13, -4, 13, 4, 13, 0, 14,
263  -10, 15, 10, 15, -5, 17, 5, 17, 0, 18,
264  -12, 19, 13, 19, -6, 22, 6, 22, 0, 23,
265  0, 0
266 };
267 
268 typedef struct SANMVideoContext {
271 
273  uint32_t pal[PALETTE_SIZE];
275 
276  ptrdiff_t pitch;
277  int width, height;
279  int prev_seq;
280 
282  uint16_t *fbuf, *frm0, *frm1, *frm2;
283  uint8_t *stored_frame;
285  uint32_t stor_size;
287 
288  uint8_t *rle_buf;
289  unsigned int rle_buf_size;
290 
292 
293  uint16_t codebook[256];
294  uint16_t small_codebook[4];
295 
296  int8_t p4x4glyphs[NGLYPHS][16];
297  int8_t p8x8glyphs[NGLYPHS][64];
298  uint8_t c47itbl[0x10000];
299  uint8_t c23lut[256];
300  uint8_t c4tbl[2][256][16];
301  uint16_t c4param;
302  uint8_t c47cb[4];
303  uint8_t c45tbl1[0x300];
304  uint8_t c45tbl2[0x8000];
306 
307 enum GlyphEdge {
313 };
314 
315 enum GlyphDir {
321 };
322 
323 /**
324  * Return enum GlyphEdge of box where point (x, y) lies.
325  *
326  * @param x x point coordinate
327  * @param y y point coordinate
328  * @param edge_size box width/height.
329  */
330 static enum GlyphEdge which_edge(int x, int y, int edge_size)
331 {
332  const int edge_max = edge_size - 1;
333 
334  if (!y)
335  return BOTTOM_EDGE;
336  else if (y == edge_max)
337  return TOP_EDGE;
338  else if (!x)
339  return LEFT_EDGE;
340  else if (x == edge_max)
341  return RIGHT_EDGE;
342  else
343  return NO_EDGE;
344 }
345 
346 static enum GlyphDir which_direction(enum GlyphEdge edge0, enum GlyphEdge edge1)
347 {
348  if ((edge0 == LEFT_EDGE && edge1 == RIGHT_EDGE) ||
349  (edge1 == LEFT_EDGE && edge0 == RIGHT_EDGE) ||
350  (edge0 == BOTTOM_EDGE && edge1 != TOP_EDGE) ||
351  (edge1 == BOTTOM_EDGE && edge0 != TOP_EDGE))
352  return DIR_UP;
353  else if ((edge0 == TOP_EDGE && edge1 != BOTTOM_EDGE) ||
354  (edge1 == TOP_EDGE && edge0 != BOTTOM_EDGE))
355  return DIR_DOWN;
356  else if ((edge0 == LEFT_EDGE && edge1 != RIGHT_EDGE) ||
357  (edge1 == LEFT_EDGE && edge0 != RIGHT_EDGE))
358  return DIR_LEFT;
359  else if ((edge0 == TOP_EDGE && edge1 == BOTTOM_EDGE) ||
360  (edge1 == TOP_EDGE && edge0 == BOTTOM_EDGE) ||
361  (edge0 == RIGHT_EDGE && edge1 != LEFT_EDGE) ||
362  (edge1 == RIGHT_EDGE && edge0 != LEFT_EDGE))
363  return DIR_RIGHT;
364 
365  return NO_DIR;
366 }
367 
368 /* Interpolate two points. */
369 static void interp_point(int8_t *points, int x0, int y0, int x1, int y1,
370  int pos, int npoints)
371 {
372  if (npoints) {
373  points[0] = (x0 * pos + x1 * (npoints - pos) + (npoints >> 1)) / npoints;
374  points[1] = (y0 * pos + y1 * (npoints - pos) + (npoints >> 1)) / npoints;
375  } else {
376  points[0] = x0;
377  points[1] = y0;
378  }
379 }
380 
381 /**
382  * Construct glyphs by iterating through vector coordinates.
383  *
384  * @param pglyphs pointer to table where glyphs are stored
385  * @param xvec pointer to x component of vector coordinates
386  * @param yvec pointer to y component of vector coordinates
387  * @param side_length glyph width/height.
388  */
389 static void make_glyphs(int8_t *pglyphs, const int8_t *xvec, const int8_t *yvec,
390  const int side_length)
391 {
392  const int glyph_size = side_length * side_length;
393  int8_t *pglyph = pglyphs;
394 
395  int i, j;
396  for (i = 0; i < GLYPH_COORD_VECT_SIZE; i++) {
397  int x0 = xvec[i];
398  int y0 = yvec[i];
399  enum GlyphEdge edge0 = which_edge(x0, y0, side_length);
400 
401  for (j = 0; j < GLYPH_COORD_VECT_SIZE; j++, pglyph += glyph_size) {
402  int x1 = xvec[j];
403  int y1 = yvec[j];
404  enum GlyphEdge edge1 = which_edge(x1, y1, side_length);
405  enum GlyphDir dir = which_direction(edge0, edge1);
406  int npoints = FFMAX(FFABS(x1 - x0), FFABS(y1 - y0));
407  int ipoint;
408 
409  for (ipoint = 0; ipoint <= npoints; ipoint++) {
410  int8_t point[2];
411  int irow, icol;
412 
413  interp_point(point, x0, y0, x1, y1, ipoint, npoints);
414 
415  switch (dir) {
416  case DIR_UP:
417  for (irow = point[1]; irow >= 0; irow--)
418  pglyph[point[0] + irow * side_length] = 1;
419  break;
420 
421  case DIR_DOWN:
422  for (irow = point[1]; irow < side_length; irow++)
423  pglyph[point[0] + irow * side_length] = 1;
424  break;
425 
426  case DIR_LEFT:
427  for (icol = point[0]; icol >= 0; icol--)
428  pglyph[icol + point[1] * side_length] = 1;
429  break;
430 
431  case DIR_RIGHT:
432  for (icol = point[0]; icol < side_length; icol++)
433  pglyph[icol + point[1] * side_length] = 1;
434  break;
435  }
436  }
437  }
438  }
439 }
440 
441 static void init_sizes(SANMVideoContext *ctx, int width, int height)
442 {
443  ctx->width = width;
444  ctx->height = height;
445  ctx->npixels = width * height;
446 
447  ctx->aligned_width = FFALIGN(width, 8);
448  ctx->aligned_height = FFALIGN(height, 8);
449 
450  ctx->buf_size = ctx->aligned_width * ctx->aligned_height * sizeof(ctx->frm0[0]);
451  ctx->pitch = width;
452 }
453 
455 {
456  av_freep(&ctx->fbuf);
457  av_freep(&ctx->frm0);
458  av_freep(&ctx->frm1);
459  av_freep(&ctx->frm2);
460  av_freep(&ctx->stored_frame);
461  av_freep(&ctx->rle_buf);
462  ctx->frm0_size =
463  ctx->frm1_size =
464  ctx->frm2_size = 0;
465  init_sizes(ctx, 0, 0);
466 }
467 
469 {
470  av_fast_padded_mallocz(&ctx->fbuf, &ctx->fbuf_size, ctx->buf_size);
471  av_fast_padded_mallocz(&ctx->frm0, &ctx->frm0_size, ctx->buf_size);
472  av_fast_padded_mallocz(&ctx->frm1, &ctx->frm1_size, ctx->buf_size);
473  av_fast_padded_mallocz(&ctx->frm2, &ctx->frm2_size, ctx->buf_size);
474  if (!ctx->version) {
475  av_fast_padded_mallocz(&ctx->stored_frame,
476  &ctx->stored_frame_size, ctx->buf_size);
477  ctx->stor_size = 0;
478  }
479 
480  if (!ctx->frm0 || !ctx->frm1 || !ctx->frm2 ||
481  (!ctx->stored_frame && !ctx->version)) {
483  return AVERROR(ENOMEM);
484  }
485 
486  return 0;
487 }
488 
489 static void codec33_gen_tiles(SANMVideoContext *ctx, int8_t param1)
490 {
491  uint8_t *dst = &(ctx->c4tbl[0][0][0]);
492  int i, j, k, l, m, n, o, p;
493 
494  for (i = 0; i < 8; i++) {
495  for (k = 0; k < 8; k++) {
496  j = i + param1;
497  l = k + param1;
498  p = (j + l) >> 1;
499  n = (j + p) >> 1;
500  m = (p + l) >> 1;
501 
502  *dst++ = p; *dst++ = p; *dst++ = n; *dst++ = j;
503  *dst++ = p; *dst++ = p; *dst++ = n; *dst++ = j;
504  *dst++ = m; *dst++ = m; *dst++ = p; *dst++ = j;
505  *dst++ = l; *dst++ = l; *dst++ = m; *dst++ = p;
506  }
507  }
508 
509  for (i = 0; i < 8; i++) {
510  for (k = 0; k < 8; k++) {
511  j = i + param1;
512  l = k + param1;
513  n = (j + l) >> 1;
514  m = (l + n) >> 1;
515 
516  *dst++ = j; *dst++ = j; *dst++ = j; *dst++ = j;
517  *dst++ = n; *dst++ = n; *dst++ = n; *dst++ = n;
518  *dst++ = m; *dst++ = m; *dst++ = m; *dst++ = m;
519  *dst++ = l; *dst++ = l; *dst++ = l; *dst++ = l;
520  }
521  }
522 
523  for (i = 0; i < 8; i++) {
524  for (k = 0; k < 8; k++) {
525  j = i + param1;
526  l = k + param1;
527  m = (j + l) >> 1;
528  n = (j + m) >> 1;
529  o = (l + m) >> 1;
530 
531  *dst++ = j; *dst++ = j; *dst++ = n; *dst++ = m;
532  *dst++ = j; *dst++ = j; *dst++ = n; *dst++ = m;
533  *dst++ = n; *dst++ = n; *dst++ = m; *dst++ = o;
534  *dst++ = m; *dst++ = m; *dst++ = o; *dst++ = l;
535  }
536  }
537 
538  for (i = 0; i < 8; i++) {
539  for (k = 0; k < 8; k++) {
540  j = i + param1;
541  l = k + param1;
542  m = (j + l) >> 1;
543  n = (l + m) >> 1;
544 
545  *dst++ = j; *dst++ = m; *dst++ = n; *dst++ = l;
546  *dst++ = j; *dst++ = m; *dst++ = n; *dst++ = l;
547  *dst++ = j; *dst++ = m; *dst++ = n; *dst++ = l;
548  *dst++ = j; *dst++ = m; *dst++ = n; *dst++ = l;
549  }
550  }
551 }
552 
553 static void codec4_gen_tiles(SANMVideoContext *ctx, uint16_t param1)
554 {
555  uint8_t *dst = &(ctx->c4tbl[0][0][0]);
556  int i, j, k, l, m, n, o;
557 
558  for (i = 1; i < 16; i += 2) {
559  for (k = 0; k < 16; k++) {
560  j = i + param1;
561  l = k + param1;
562  m = (j + l) / 2;
563  n = (j + m) / 2;
564  o = (l + m) / 2;
565  if (j == m || l == m) {
566  *dst++ = l; *dst++ = j; *dst++ = l; *dst++ = j;
567  *dst++ = j; *dst++ = l; *dst++ = j; *dst++ = j;
568  *dst++ = l; *dst++ = j; *dst++ = l; *dst++ = j;
569  *dst++ = l; *dst++ = l; *dst++ = j; *dst++ = l;
570  } else {
571  *dst++ = m; *dst++ = m; *dst++ = n; *dst++ = j;
572  *dst++ = m; *dst++ = m; *dst++ = n; *dst++ = j;
573  *dst++ = o; *dst++ = o; *dst++ = m; *dst++ = n;
574  *dst++ = l; *dst++ = l; *dst++ = o; *dst++ = m;
575  }
576  }
577  }
578 
579  for (i = 0; i < 16; i += 2) {
580  for (k = 0; k < 16; k++) {
581  j = i + param1;
582  l = k + param1;
583  m = (j + l) / 2;
584  n = (j + m) / 2;
585  o = (l + m) / 2;
586  if (m == j || m == l) {
587  *dst++ = j; *dst++ = j; *dst++ = l; *dst++ = j;
588  *dst++ = j; *dst++ = j; *dst++ = j; *dst++ = l;
589  *dst++ = l; *dst++ = j; *dst++ = l; *dst++ = l;
590  *dst++ = j; *dst++ = l; *dst++ = j; *dst++ = l;
591  } else {
592  *dst++ = j; *dst++ = j; *dst++ = n; *dst++ = m;
593  *dst++ = j; *dst++ = j; *dst++ = n; *dst++ = m;
594  *dst++ = n; *dst++ = n; *dst++ = m; *dst++ = o;
595  *dst++ = m; *dst++ = m; *dst++ = o; *dst++ = l;
596  }
597  }
598  }
599 }
600 
601 
603  uint16_t param2, uint8_t clr)
604 {
605  uint8_t c, *dst = (uint8_t *)&(ctx->c4tbl[1][0][0]);
606  uint32_t loop = param2 * 8;
607 
608  if ((param2 > 256) || (bytestream2_get_bytes_left(gb) < loop))
609  return AVERROR_INVALIDDATA;
610 
611  while (loop--) {
612  c = bytestream2_get_byteu(gb);
613  *dst++ = (c >> 4) + clr;
614  *dst++ = (c & 0xf) + clr;
615  }
616 
617  return 0;
618 }
619 
620 static void rotate_bufs(SANMVideoContext *ctx, int rotate_code)
621 {
622  if (rotate_code == 2)
623  FFSWAP(uint16_t*, ctx->frm1, ctx->frm2);
624  FFSWAP(uint16_t*, ctx->frm2, ctx->frm0);
625 }
626 
628 {
629  SANMVideoContext *ctx = avctx->priv_data;
630 
631  ctx->avctx = avctx;
632  ctx->version = !avctx->extradata_size;
633  // early sanity check before allocations to avoid need for deallocation code.
634  if (!ctx->version && avctx->extradata_size < 1026) {
635  av_log(avctx, AV_LOG_ERROR, "Not enough extradata.\n");
636  return AVERROR_INVALIDDATA;
637  }
638 
639  avctx->pix_fmt = ctx->version ? AV_PIX_FMT_RGB565 : AV_PIX_FMT_PAL8;
640 
641  if (!ctx->version) {
642  // ANIM valid range is 2x2 up to 640x480. If the given
643  // width/height are within that range, lock the dimensions
644  // and forego future changes in process_frame_obj().
645  // NOTE: the smush demuxer passes 0/0 since ANM/SAN files
646  // have no dimension information in their header.
647  if (avctx->width != 0 || avctx->height != 0) {
648  if ((avctx->width < 2) || (avctx->height < 2))
649  return AVERROR_INVALIDDATA;
650  if ((avctx->width <= 640) && (avctx->height <= 480))
651  ctx->have_dimensions = 1;
652  else
653  return AVERROR_INVALIDDATA;
654  }
655  } else if (avctx->width > 800 || avctx->height > 600 ||
656  avctx->width < 8 || avctx->height < 8) {
657  // BL16 valid range is 8x8 - 800x600
658  return AVERROR_INVALIDDATA;
659  }
660  init_sizes(ctx, avctx->width, avctx->height);
661  if (init_buffers(ctx)) {
662  av_log(avctx, AV_LOG_ERROR, "Error allocating buffers.\n");
663  return AVERROR(ENOMEM);
664  }
665 
666  make_glyphs(ctx->p4x4glyphs[0], glyph4_x, glyph4_y, 4);
667  make_glyphs(ctx->p8x8glyphs[0], glyph8_x, glyph8_y, 8);
668 
669  if (!ctx->version) {
670  int i;
671 
672  ctx->subversion = AV_RL16(avctx->extradata);
673  for (i = 0; i < PALETTE_SIZE; i++)
674  ctx->pal[i] = 0xFFU << 24 | AV_RL32(avctx->extradata + 2 + i * 4);
675  if (ctx->subversion < 2)
676  ctx->pal[0] = 0xFFU << 24;
677  }
678  ctx->c4param = 0xffff;
679 
680  return 0;
681 }
682 
684 {
685  SANMVideoContext *ctx = avctx->priv_data;
686 
688 
689  return 0;
690 }
691 
692 static int old_codec4(SANMVideoContext *ctx, GetByteContext *gb, int top, int left,
693  int w, int h, uint8_t param, uint16_t param2, int codec)
694 {
695  const uint16_t mx = ctx->width, my = ctx->height, p = ctx->pitch;
696  uint8_t mask, bits, idx, *gs, *dst = (uint8_t *)ctx->fbuf;
697  int i, j, k, l, bit, ret, x, y;
698 
699  if (ctx->c4param != param) {
700  if (codec > 32)
701  codec33_gen_tiles(ctx, param);
702  else
703  codec4_gen_tiles(ctx, param);
704  ctx->c4param = param;
705  }
706  if (param2 > 0) {
707  ret = codec4_load_tiles(ctx, gb, param2, param);
708  if (ret)
709  return ret;
710  }
711 
712  if (codec > 32)
713  codec -= 29;
714 
715  for (j = 0; j < w; j += 4) {
716  mask = bits = 0;
717  x = left + j;
718  for (i = 0; i < h; i += 4) {
719  y = top + i;
720  if (param2 > 0) {
721  if (bits == 0) {
722  if (bytestream2_get_bytes_left(gb) < 1)
723  return AVERROR_INVALIDDATA;
724  mask = bytestream2_get_byteu(gb);
725  bits = 8;
726  }
727  bit = !!(mask & 0x80);
728  mask <<= 1;
729  bits--;
730  } else {
731  bit = 0;
732  }
733 
734  if (bytestream2_get_bytes_left(gb) < 1)
735  return AVERROR_INVALIDDATA;
736  idx = bytestream2_get_byteu(gb);
737  if ((bit == 0) && (idx == 0x80) && (codec != 5))
738  continue;
739  if ((y >= my) || ((y + 4) < 0) || ((x + 4) < 0) || (x >= mx))
740  continue;
741  gs = &(ctx->c4tbl[bit][idx][0]);
742  if ((y >= 0) && (x >= 0) && ((y + 4) < my) && ((x + 4) < mx)) {
743  for (k = 0; k < 4; k++, gs += 4)
744  memcpy(dst + x + (y + k) * p, gs, 4);
745  } else {
746  for (k = 0; k < 4; k++) {
747  for (l = 0; l < 4; l++, gs++) {
748  const int yo = y + k, xo = x + l;
749  if ((yo >= 0) && (yo < my) && (xo >= 0) && (xo < mx))
750  *(dst + yo * p + xo) = *gs;
751  }
752  }
753  }
754  }
755  }
756  return 0;
757 }
758 
759 static int rle_decode(SANMVideoContext *ctx, GetByteContext *gb, uint8_t *dst, const int out_size)
760 {
761  int opcode, color, run_len, left = out_size;
762 
763  while (left > 0) {
764  opcode = bytestream2_get_byte(gb);
765  run_len = (opcode >> 1) + 1;
766  if (run_len > left || bytestream2_get_bytes_left(gb) <= 0)
767  return AVERROR_INVALIDDATA;
768 
769  if (opcode & 1) {
770  color = bytestream2_get_byte(gb);
771  memset(dst, color, run_len);
772  } else {
774  return AVERROR_INVALIDDATA;
776  }
777 
778  dst += run_len;
779  left -= run_len;
780  }
781 
782  return 0;
783 }
784 
785 static int old_codec23(SANMVideoContext *ctx, GetByteContext *gb, int top, int left,
786  int width, int height, uint8_t param, uint16_t param2)
787 {
788  const uint16_t mx = ctx->width, my = ctx->height, p = ctx->pitch;
789  uint8_t c, lut[256], *dst = (uint8_t *)ctx->fbuf;
790  int sk, i, j, ls, pc, y;
791 
792  if (ctx->subversion < 2) {
793  /* Rebel Assault 1: constant offset + 0xd0 */
794  for (i = 0; i < 256; i++)
795  lut[i] = (i + param + 0xd0) & 0xff;
796  } else if (param2 == 256) {
797  if (bytestream2_get_bytes_left(gb) < 256)
798  return AVERROR_INVALIDDATA;
799  bytestream2_get_bufferu(gb, ctx->c23lut, 256);
800  } else if (param2 < 256) {
801  for (i = 0; i < 256; i++)
802  lut[i] = (i + param2) & 0xff;
803  } else {
804  memcpy(lut, ctx->c23lut, 256);
805  }
806  if (bytestream2_get_bytes_left(gb) < 1)
807  return 0; /* some c23 frames just set up the LUT */
808 
809  if (((top + height) < 0) || (top >= my) || (left + width < 0) || (left >= mx))
810  return 0;
811 
812  if (top < 0) {
813  y = -top;
814  while (y-- && bytestream2_get_bytes_left(gb) > 1) {
815  ls = bytestream2_get_le16u(gb);
816  if (bytestream2_get_bytes_left(gb) < ls)
817  return AVERROR_INVALIDDATA;
818  bytestream2_skip(gb, ls);
819  }
820  height += top;
821  top = 0;
822  }
823 
824  y = top;
825  for (; (bytestream2_get_bytes_left(gb) > 1) && (height > 0) && (y < my); height--, y++) {
826  ls = bytestream2_get_le16u(gb);
827  sk = 1;
828  pc = left;
829  while ((bytestream2_get_bytes_left(gb) > 0) && (ls > 0) && (pc <= (width + left))) {
830  j = bytestream2_get_byteu(gb);
831  ls--;
832  if (!sk) {
833  while (j--) {
834  if ((pc >= 0) && (pc < mx)) {
835  c = *(dst + (y * p) + pc);
836  *(dst + (y * p) + pc) = lut[c];
837  }
838  if (pc < mx)
839  pc++;
840  }
841  } else {
842  if (pc < mx)
843  pc += j;
844  }
845  sk ^= 1;
846  }
847  }
848  return 0;
849 }
850 
851 static int old_codec21(SANMVideoContext *ctx, GetByteContext *gb, int top, int left,
852  int width, int height)
853 {
854  const uint16_t mx = ctx->width, my = ctx->height, p = ctx->pitch;
855  uint8_t *dst = (uint8_t *)ctx->fbuf, c;
856  int j, y, pc, sk, ls;
857 
858  if (((top + height) < 0) || (top >= my) || (left + width < 0) || (left >= mx))
859  return 0;
860 
861  y = top;
862  for (; (bytestream2_get_bytes_left(gb) > 2) && (height > 0) && (y < my); height--, y++) {
863  ls = bytestream2_get_le16u(gb);
864  if (y < 0) {
865  if (ls >= bytestream2_get_bytes_left(gb))
866  return 0;
867  bytestream2_skip(gb, ls);
868  continue;
869  }
870  sk = 1;
871  pc = left;
872  while ((bytestream2_get_bytes_left(gb) > 1) && (ls > 1) && (pc <= (width + left))) {
873  j = bytestream2_get_le16u(gb);
874  ls -= 2;
875  if (sk) {
876  if (pc < mx)
877  pc += j;
878  } else {
879  while ((bytestream2_get_bytes_left(gb) > 0) && (ls > 0) && (j >= 0)) {
880  c = bytestream2_get_byteu(gb);
881  if ((pc >= 0) && (pc < mx)) {
882  *(dst + (y * p) + pc) = c;
883  }
884  ls--;
885  j--;
886  if (pc < mx)
887  pc++;
888  }
889  }
890  sk ^= 1;
891  }
892  }
893  return 0;
894 }
895 
896 static int old_codec1(SANMVideoContext *ctx, GetByteContext *gb, int top,
897  int left, int width, int height, int opaque)
898 {
899  const uint16_t mx = ctx->width, my = ctx->height, p = ctx->pitch;
900  uint8_t *dst = (uint8_t *)ctx->fbuf, code, c;
901  int j, x, y, flag, dlen;
902 
903  if (((top + height) < 0) || (top >= my) || (left + width < 0) || (left >= mx))
904  return 0;
905 
906  if (top < 0) {
907  y = -top;
908  while (y-- && bytestream2_get_bytes_left(gb) > 1) {
909  dlen = bytestream2_get_le16u(gb);
910  if (bytestream2_get_bytes_left(gb) <= dlen)
911  return AVERROR_INVALIDDATA;
912  bytestream2_skip(gb, dlen);
913  }
914  height += top;
915  top = 0;
916  }
917 
918  y = top;
919  for (; (bytestream2_get_bytes_left(gb) > 1) && (height > 0) && (y < my); height--, y++) {
920  dlen = bytestream2_get_le16u(gb);
921  x = left;
922  while (bytestream2_get_bytes_left(gb) > 1 && dlen) {
923  code = bytestream2_get_byteu(gb);
924  dlen--;
925  flag = code & 1;
926  code = (code >> 1) + 1;
927  if (flag) {
928  c = bytestream2_get_byteu(gb);
929  dlen--;
930  if (x >= mx)
931  continue;
932  if (x < 0) {
933  int dff = FFMIN(-x, code);
934  code -= dff;
935  x += dff;
936  }
937  if (x + code >= mx)
938  code = mx - x;
939  if (code < 1)
940  continue;
941  for (j = 0; (j < code) && (c || opaque); j++) {
942  *(dst + (y * p) + x + j) = c;
943  }
944  x += code;
945  } else {
947  return AVERROR_INVALIDDATA;
948  for (j = 0; j < code; j++) {
949  c = bytestream2_get_byteu(gb);
950  if ((x >= 0) && (x < mx) && (c || opaque))
951  *(dst + (y * p) + x) = c;
952  if (x < mx)
953  x++;
954  }
955  dlen -= code;
956  }
957  }
958  }
959 
960  return 0;
961 }
962 
963 static int old_codec31(SANMVideoContext *ctx, GetByteContext *gb, int top,
964  int left, int width, int height, int p1, int opaque)
965 {
966  const uint16_t mx = ctx->width, my = ctx->height, p = ctx->pitch;
967  uint8_t *dst = (uint8_t *)ctx->fbuf, c;
968  int j, x, y, flag, dlen, code;
969 
970  if (((top + height) < 0) || (top >= my) || (left + width < 0) || (left >= mx))
971  return 0;
972 
973  if (top < 0) {
974  y = -top;
975  while (y-- && bytestream2_get_bytes_left(gb) > 1) {
976  dlen = bytestream2_get_le16u(gb);
977  if (bytestream2_get_bytes_left(gb) <= dlen)
978  return AVERROR_INVALIDDATA;
979  bytestream2_skip(gb, dlen);
980  }
981  height += top;
982  top = 0;
983  }
984 
985  y = top;
986  for (; (bytestream2_get_bytes_left(gb) > 1) && (height > 0) && (y < my); height--, y++) {
987  dlen = bytestream2_get_le16u(gb);
988  x = left;
989  while (bytestream2_get_bytes_left(gb) > 1 && dlen) {
990  code = bytestream2_get_byteu(gb);
991  dlen--;
992  flag = code & 1;
993  code = (code >> 1) + 1;
994  if (flag) {
995  c = bytestream2_get_byteu(gb);
996  dlen--;
997  for (j = 0; (j < code); j++) {
998  if ((opaque || (c & 0xf)) && (x >= 0) && (x < mx))
999  *(dst + (y * p) + x) = p1 + (c & 0xf);
1000  if (x < mx)
1001  x++;
1002  if ((opaque || (c >> 4)) && (x >= 0) && (x < mx))
1003  *(dst + (y * p) + x) = p1 + (c >> 4);
1004  if (x < mx)
1005  x++;
1006  }
1007  } else {
1008  if (bytestream2_get_bytes_left(gb) < code)
1009  return AVERROR_INVALIDDATA;
1010  for (j = 0; j < code; j++) {
1011  c = bytestream2_get_byteu(gb);
1012  if ((opaque || (c & 0xf)) && (x >= 0) && (x < mx))
1013  *(dst + (y * p) + x) = p1 + (c & 0xf);
1014  if (x < mx)
1015  x++;
1016  if ((opaque || (c >> 4)) && (x >= 0) && (x < mx))
1017  *(dst + (y * p) + x) = p1 + (c >> 4);
1018  if (x < mx)
1019  x++;
1020  }
1021  dlen -= code;
1022  }
1023  }
1024  }
1025 
1026  return 0;
1027 }
1028 
1029 static int old_codec2(SANMVideoContext *ctx, GetByteContext *gb, int top,
1030  int left, int width, int height)
1031 {
1032  uint8_t *dst = (uint8_t *)ctx->fbuf, col;
1033  int16_t xpos = left, ypos = top;
1034 
1035  while (bytestream2_get_bytes_left(gb) > 3) {
1036  xpos += bytestream2_get_le16u(gb);
1037  ypos += bytestream2_get_byteu(gb);
1038  col = bytestream2_get_byteu(gb);
1039  if (xpos >= 0 && ypos >= 0 &&
1040  xpos < ctx->width && ypos < ctx->height) {
1041  *(dst + xpos + ypos * ctx->pitch) = col;
1042  }
1043  }
1044  return 0;
1045 }
1046 
1047 static void blt_solid(uint8_t *dst, const uint8_t *src, int16_t left, int16_t top,
1048  uint16_t srcxoff, uint16_t srcyoff, uint16_t srcwidth,
1049  uint16_t srcheight, const uint16_t srcpitch, const uint16_t dstpitch,
1050  const uint16_t dstheight, int32_t size)
1051 {
1052  if ((srcwidth < 1) || (srcheight < 1) || (size < 1))
1053  return;
1054 
1055  if (top < 0) {
1056  if (-top >= srcheight)
1057  return;
1058  srcyoff -= top;
1059  srcheight += top;
1060  size += (srcpitch * top);
1061  top = 0;
1062  }
1063 
1064  if ((top + srcheight) > dstheight) {
1065  int clip = (top + srcheight) - dstheight;
1066  if (clip >= srcheight)
1067  return;
1068  srcheight -= clip;
1069  }
1070 
1071  if (left < 0) {
1072  if (-left >= srcwidth)
1073  return;
1074  srcxoff -= left;
1075  srcwidth += left;
1076  size += left;
1077  left = 0;
1078  }
1079 
1080  if (left + srcwidth > dstpitch) {
1081  int clip = (left + srcwidth) - dstpitch;
1082  if (clip >= srcwidth)
1083  return;
1084  srcwidth -= clip;
1085  }
1086 
1087  src += ((uintptr_t)srcyoff * srcpitch) + srcxoff;
1088  dst += ((uintptr_t)top * dstpitch) + left;
1089  while ((srcheight--) && (size >= srcwidth)) {
1090  memcpy(dst, src, srcwidth);
1091  src += srcpitch;
1092  dst += dstpitch;
1093  size -= srcpitch;
1094  }
1095  if ((size > 0) && (size < srcwidth) && (srcheight > 0))
1096  memcpy(dst, src, size);
1097 }
1098 
1099 static void blt_mask(uint8_t *dst, const uint8_t *src, int16_t left, int16_t top,
1100  uint16_t srcxoff, uint16_t srcyoff, uint16_t srcwidth,
1101  uint16_t srcheight, const uint16_t srcpitch, const uint16_t dstpitch,
1102  const uint16_t dstheight, int32_t size, const uint8_t skipcolor)
1103 {
1104  if ((srcwidth < 1) || (srcheight < 1) || (size < 1))
1105  return;
1106 
1107  if (top < 0) {
1108  if (-top >= srcheight)
1109  return;
1110  srcyoff -= top;
1111  srcheight += top;
1112  size += (srcpitch * top);
1113  top = 0;
1114  }
1115 
1116  if ((top + srcheight) > dstheight) {
1117  int clip = (top + srcheight) - dstheight;
1118  if (clip >= srcheight)
1119  return;
1120  srcheight -= clip;
1121  }
1122 
1123  if (left < 0) {
1124  if (-left >= srcwidth)
1125  return;
1126  srcxoff -= left;
1127  srcwidth += left;
1128  size += left;
1129  left = 0;
1130  }
1131 
1132  if (left + srcwidth > dstpitch) {
1133  int clip = (left + srcwidth) - dstpitch;
1134  if (clip >= srcwidth)
1135  return;
1136  srcwidth -= clip;
1137  }
1138 
1139  src += ((uintptr_t)srcyoff * srcpitch) + srcxoff;
1140  dst += ((uintptr_t)top * dstpitch) + left;
1141  for (int i = 0; (size > 0) && (i < srcheight); i++) {
1142  for (int j = 0; (size > 0) && (j < srcwidth); j++, size--) {
1143  if (src[j] != skipcolor)
1144  dst[j] = src[j];
1145  }
1146  src += srcpitch;
1147  dst += dstpitch;
1148  }
1149 }
1150 
1151 static void blt_ipol(uint8_t *dst, const uint8_t *src1, const uint8_t *src2,
1152  int16_t left, int16_t top, uint16_t srcxoff, uint16_t srcyoff,
1153  uint16_t srcwidth, uint16_t srcheight, const uint16_t srcpitch,
1154  const uint16_t dstpitch, const uint16_t dstheight, int32_t size,
1155  const uint8_t *itbl)
1156 {
1157  if ((srcwidth < 1) || (srcheight < 1) || (size < 1))
1158  return;
1159 
1160  if (top < 0) {
1161  if (-top >= srcheight)
1162  return;
1163  srcyoff -= top;
1164  srcheight += top;
1165  size += (srcpitch * top);
1166  top = 0;
1167  }
1168 
1169  if ((top + srcheight) > dstheight) {
1170  int clip = (top + srcheight) - dstheight;
1171  if (clip >= srcheight)
1172  return;
1173  srcheight -= clip;
1174  }
1175 
1176  if (left < 0) {
1177  if (-left >= srcwidth)
1178  return;
1179  srcxoff -= left;
1180  srcwidth += left;
1181  size += left;
1182  left = 0;
1183  }
1184 
1185  if (left + srcwidth > dstpitch) {
1186  int clip = (left + srcwidth) - dstpitch;
1187  if (clip >= srcwidth)
1188  return;
1189  srcwidth -= clip;
1190  }
1191 
1192  src1 += ((uintptr_t)srcyoff * srcpitch) + srcxoff;
1193  src2 += ((uintptr_t)srcyoff * srcpitch) + srcxoff;
1194  dst += ((uintptr_t)top * dstpitch) + left;
1195  for (int i = 0; (size > 0) && (i < srcheight); i++) {
1196  for (int j = 0; (size > 0) && (j < srcwidth); j++, size--) {
1197  dst[j] = itbl[(src1[j] << 8) | src2[j]];
1198  }
1199  src1 += srcpitch;
1200  src2 += srcpitch;
1201  dst += dstpitch;
1202  }
1203 }
1204 
1205 static int old_codec20(SANMVideoContext *ctx, GetByteContext *gb, int top, int left,
1206  const int w, const int h)
1207 {
1208  blt_solid((uint8_t*)ctx->fbuf, gb->buffer, left, top, 0, 0, w, h, w, ctx->pitch,
1209  ctx->height, FFMIN(bytestream2_get_bytes_left(gb), w * h));
1210 
1211  return 0;
1212 }
1213 
1214 static inline void codec37_mv(uint8_t *dst, const uint8_t *src,
1215  int height, int stride, int x, int y)
1216 {
1217  int pos, i, j;
1218 
1219  pos = x + y * stride;
1220  for (j = 0; j < 4; j++) {
1221  for (i = 0; i < 4; i++) {
1222  if ((pos + i) < 0 || (pos + i) >= height * stride)
1223  dst[i] = 0;
1224  else
1225  dst[i] = src[i];
1226  }
1227  dst += stride;
1228  src += stride;
1229  pos += stride;
1230  }
1231 }
1232 
1233 static int old_codec37(SANMVideoContext *ctx, GetByteContext *gb, int top, int left,
1234  int width, int height)
1235 {
1236  int i, j, k, l, t, run, len, code, skip, mx, my;
1237  uint8_t *dst, *prev;
1238  int skip_run = 0;
1239 
1240  width = FFALIGN(width, 4);
1241  if (width > ctx->aligned_width)
1242  return AVERROR_INVALIDDATA;
1243 
1244  if (bytestream2_get_bytes_left(gb) < 16)
1245  return AVERROR_INVALIDDATA;
1246 
1247  int compr = bytestream2_get_byteu(gb);
1248  int mvoff = bytestream2_get_byteu(gb);
1249  int seq = bytestream2_get_le16u(gb);
1250  uint32_t decoded_size = bytestream2_get_le32u(gb);
1251  int flags;
1252 
1253  bytestream2_skip(gb, 4);
1254  flags = bytestream2_get_byteu(gb);
1255  bytestream2_skip(gb, 3);
1256 
1257  if (decoded_size > height * width) {
1258  decoded_size = height * width;
1259  av_log(ctx->avctx, AV_LOG_WARNING, "Decoded size is too large.\n");
1260  }
1261 
1262  if (((seq & 1) || !(flags & 1)) && (compr && compr != 2)) {
1263  FFSWAP(uint16_t*, ctx->frm0, ctx->frm2);
1264  }
1265 
1266  dst = ((uint8_t*)ctx->frm0);
1267  prev = ((uint8_t*)ctx->frm2);
1268 
1269  if (mvoff > 2) {
1270  av_log(ctx->avctx, AV_LOG_ERROR, "Invalid motion base value %d.\n", mvoff);
1271  return AVERROR_INVALIDDATA;
1272  }
1273 
1274  switch (compr) {
1275  case 0:
1277  return AVERROR_INVALIDDATA;
1279  memset(ctx->frm2, 0, ctx->frm2_size);
1280  break;
1281  case 1:
1282  run = 0;
1283  len = -1;
1284  code = 0;
1285 
1286  for (j = 0; j < height; j += 4) {
1287  for (i = 0; i < width; i += 4) {
1288  if (len < 0) {
1289  if (bytestream2_get_bytes_left(gb) < 1)
1290  return AVERROR_INVALIDDATA;
1291  code = bytestream2_get_byte(gb);
1292  len = code >> 1;
1293  run = code & 1;
1294  skip = 0;
1295  } else {
1296  skip = run;
1297  }
1298 
1299  if (!skip) {
1300  if (bytestream2_get_bytes_left(gb) < 1)
1301  return AVERROR_INVALIDDATA;
1302  code = bytestream2_get_byte(gb);
1303  if (code == 0xff) {
1304  len--;
1305  for (k = 0; k < 4; k++) {
1306  for (l = 0; l < 4; l++) {
1307  if (len < 0) {
1308  if (bytestream2_get_bytes_left(gb) < 1)
1309  return AVERROR_INVALIDDATA;
1310  code = bytestream2_get_byte(gb);
1311  len = code >> 1;
1312  run = code & 1;
1313  if (run) {
1314  if (bytestream2_get_bytes_left(gb) < 1)
1315  return AVERROR_INVALIDDATA;
1316  code = bytestream2_get_byte(gb);
1317  }
1318  }
1319  if (!run) {
1320  if (bytestream2_get_bytes_left(gb) < 1)
1321  return AVERROR_INVALIDDATA;
1322  code = bytestream2_get_byte(gb);
1323  }
1324  *(dst + i + (k * width) + l) = code;
1325  len--;
1326  }
1327  }
1328  continue;
1329  }
1330  }
1331  /* 4x4 block copy from prev with MV */
1332  mx = c37_mv[(mvoff * 256 + code) * 2];
1333  my = c37_mv[(mvoff * 256 + code) * 2 + 1];
1334  codec37_mv(dst + i, prev + i + mx + my * width,
1335  height, width, i + mx, j + my);
1336  len--;
1337  }
1338  dst += width * 4;
1339  prev += width * 4;
1340  }
1341  break;
1342  case 2:
1343  if (rle_decode(ctx, gb, dst, decoded_size))
1344  return AVERROR_INVALIDDATA;
1345  memset(ctx->frm2, 0, ctx->frm2_size);
1346  break;
1347  case 3:
1348  case 4:
1349  for (j = 0; j < height; j += 4) {
1350  for (i = 0; i < width; i += 4) {
1351  int code;
1352  if (skip_run) {
1353  skip_run--;
1354  copy_block4(dst + i, prev + i, width, width, 4);
1355  continue;
1356  }
1357  if (bytestream2_get_bytes_left(gb) < 1)
1358  return AVERROR_INVALIDDATA;
1359  code = bytestream2_get_byteu(gb);
1360  if (code == 0xFF) {
1361  if (bytestream2_get_bytes_left(gb) < 16)
1362  return AVERROR_INVALIDDATA;
1363  for (k = 0; k < 4; k++)
1364  bytestream2_get_bufferu(gb, dst + i + k * width, 4);
1365  } else if ((flags & 4) && (code == 0xFE)) {
1366  if (bytestream2_get_bytes_left(gb) < 4)
1367  return AVERROR_INVALIDDATA;
1368  for (k = 0; k < 4; k += 2) {
1369  uint8_t c1 = bytestream2_get_byteu(gb);
1370  uint8_t c2 = bytestream2_get_byteu(gb);
1371  for (l = 0; l < 2; l++) {
1372  *(dst + i + ((k + l) * width) + 0) = c1;
1373  *(dst + i + ((k + l) * width) + 1) = c1;
1374  *(dst + i + ((k + l) * width) + 2) = c2;
1375  *(dst + i + ((k + l) * width) + 3) = c2;
1376  }
1377  }
1378  } else if ((flags & 4) && (code == 0xFD)) {
1379  if (bytestream2_get_bytes_left(gb) < 1)
1380  return AVERROR_INVALIDDATA;
1381  t = bytestream2_get_byteu(gb);
1382  for (k = 0; k < 4; k++)
1383  memset(dst + i + k * width, t, 4);
1384  } else {
1385  mx = c37_mv[(mvoff * 256 + code) * 2];
1386  my = c37_mv[(mvoff * 256 + code) * 2 + 1];
1387  codec37_mv(dst + i, prev + i + mx + my * width,
1388  height, width, i + mx, j + my);
1389 
1390  if ((compr == 4) && (code == 0)) {
1391  if (bytestream2_get_bytes_left(gb) < 1)
1392  return AVERROR_INVALIDDATA;
1393  skip_run = bytestream2_get_byteu(gb);
1394  }
1395  }
1396  }
1397  dst += width * 4;
1398  prev += width * 4;
1399  }
1400  break;
1401  default:
1403  "Subcodec 37 compression %d", compr);
1404  return AVERROR_PATCHWELCOME;
1405  }
1406 
1407  if ((flags & 2) == 0) {
1408  blt_solid((uint8_t*)ctx->fbuf, (uint8_t*)ctx->frm0, left, top, 0, 0, width,
1409  height, width, ctx->pitch, ctx->height, width * height);
1410  } else {
1411  blt_mask((uint8_t*)ctx->fbuf, (uint8_t*)ctx->frm0, left, top, 0, 0, width,
1412  height, width, ctx->pitch, ctx->height, width * height, 0);
1413  }
1414  return 0;
1415 }
1416 
1418  uint8_t *prev1, uint8_t *prev2, int stride, int size)
1419 {
1420  int code, k, t;
1421  uint8_t colors[2];
1422  int8_t *pglyph;
1423 
1424  if (bytestream2_get_bytes_left(gb) < 1)
1425  return AVERROR_INVALIDDATA;
1426 
1427  code = bytestream2_get_byteu(gb);
1428  if (code >= 0xF8) {
1429  switch (code) {
1430  case 0xFF:
1431  if (size == 2) {
1432  if (bytestream2_get_bytes_left(gb) < 4)
1433  return AVERROR_INVALIDDATA;
1434  dst[0] = bytestream2_get_byteu(gb);
1435  dst[1] = bytestream2_get_byteu(gb);
1436  dst[0 + stride] = bytestream2_get_byteu(gb);
1437  dst[1 + stride] = bytestream2_get_byteu(gb);
1438  } else {
1439  size >>= 1;
1440  if (codec47_block(ctx, gb, dst, prev1, prev2, stride, size))
1441  return AVERROR_INVALIDDATA;
1442  if (codec47_block(ctx, gb, dst + size, prev1 + size, prev2 + size,
1443  stride, size))
1444  return AVERROR_INVALIDDATA;
1445  dst += size * stride;
1446  prev1 += size * stride;
1447  prev2 += size * stride;
1448  if (codec47_block(ctx, gb, dst, prev1, prev2, stride, size))
1449  return AVERROR_INVALIDDATA;
1450  if (codec47_block(ctx, gb, dst + size, prev1 + size, prev2 + size,
1451  stride, size))
1452  return AVERROR_INVALIDDATA;
1453  }
1454  break;
1455  case 0xFE:
1456  if (bytestream2_get_bytes_left(gb) < 1)
1457  return AVERROR_INVALIDDATA;
1458 
1459  t = bytestream2_get_byteu(gb);
1460  for (k = 0; k < size; k++)
1461  memset(dst + k * stride, t, size);
1462  break;
1463  case 0xFD:
1464  if (bytestream2_get_bytes_left(gb) < 3)
1465  return AVERROR_INVALIDDATA;
1466 
1467  code = bytestream2_get_byteu(gb);
1468  pglyph = (size == 8) ? ctx->p8x8glyphs[code] : ctx->p4x4glyphs[code];
1469  bytestream2_get_bufferu(gb, colors, 2);
1470 
1471  for (k = 0; k < size; k++)
1472  for (t = 0; t < size; t++)
1473  dst[t + k * stride] = colors[!*pglyph++];
1474  break;
1475  case 0xFC:
1476  for (k = 0; k < size; k++)
1477  memcpy(dst + k * stride, prev1 + k * stride, size);
1478  break;
1479  default:
1480  for (k = 0; k < size; k++)
1481  memset(dst + k * stride, ctx->c47cb[code & 3], size);
1482  }
1483  } else {
1484  int mx = c47_mv[code][0];
1485  int my = c47_mv[code][1];
1486  int index = prev2 - (const uint8_t *)ctx->frm2;
1487 
1488  av_assert2(index >= 0 && index < (ctx->buf_size >> 1));
1489 
1490  if (index < -mx - my * stride ||
1491  (ctx->buf_size >> 1) - index < mx + size + (my + size - 1) * stride) {
1492  av_log(ctx->avctx, AV_LOG_ERROR, "MV is invalid.\n");
1493  return AVERROR_INVALIDDATA;
1494  }
1495 
1496  for (k = 0; k < size; k++)
1497  memcpy(dst + k * stride, prev2 + mx + (my + k) * stride, size);
1498  }
1499 
1500  return 0;
1501 }
1502 
1503 static void codec47_read_interptable(GetByteContext *gb, uint8_t *itbl)
1504 {
1505  uint8_t *p1, *p2;
1506  int i, j;
1507 
1508  for (i = 0; i < 256; i++) {
1509  p1 = p2 = itbl + i;
1510  for (j = 256 - i; j; j--) {
1511  *p1 = *p2 = bytestream2_get_byte(gb);
1512  p1 += 1;
1513  p2 += 256;
1514  }
1515  itbl += 256;
1516  }
1517 }
1518 
1519 static void codec47_comp1(GetByteContext *gb, uint8_t *dst_in, int width,
1520  const int height, const ptrdiff_t stride, const uint8_t *itbl)
1521 {
1522  uint8_t p1, *dst;
1523  uint16_t px;
1524  int i, j;
1525 
1526  dst = dst_in + stride;
1527  for (i = 0; i < height; i += 2) {
1528  p1 = bytestream2_get_byte(gb);
1529  *dst++ = p1;
1530  *dst++ = p1;
1531  px = p1;
1532  for (j = 2; j < width; j += 2) {
1533  p1 = bytestream2_get_byte(gb);
1534  px = (px << 8) | p1;
1535  *dst++ = itbl[px];
1536  *dst++ = p1;
1537  }
1538  dst += stride;
1539  }
1540 
1541  memcpy(dst_in, dst_in + stride, width);
1542  dst = dst_in + stride + stride;
1543  for (i = 2; i < height - 1; i += 2) {
1544  for (j = 0; j < width; j++) {
1545  px = (*(dst - stride) << 8) | *(dst + stride);
1546  *dst++ = itbl[px];
1547  }
1548  dst += stride;
1549  }
1550 }
1551 
1552 static int old_codec47(SANMVideoContext *ctx, GetByteContext *gb, int top, int left,
1553  int width, int height)
1554 {
1555  uint32_t decoded_size;
1556  int i, j;
1557  uint8_t *dst = (uint8_t *)ctx->frm0;
1558  uint8_t *prev1 = (uint8_t *)ctx->frm1;
1559  uint8_t *prev2 = (uint8_t *)ctx->frm2;
1560  uint8_t auxcol[2];
1561 
1562  width = FFALIGN(width, 8);
1563  if (width > ctx->aligned_width)
1564  return AVERROR_INVALIDDATA;
1565 
1566  if (bytestream2_get_bytes_left(gb) < 26)
1567  return AVERROR_INVALIDDATA;
1568 
1569  int seq = bytestream2_get_le16u(gb);
1570  int compr = bytestream2_get_byteu(gb);
1571  int new_rot = bytestream2_get_byteu(gb);
1572  int skip = bytestream2_get_byteu(gb);
1573 
1574  bytestream2_skip(gb, 3);
1575  bytestream2_get_bufferu(gb, ctx->c47cb, 4);
1576  auxcol[0] = bytestream2_get_byteu(gb);
1577  auxcol[1] = bytestream2_get_byteu(gb);
1578  decoded_size = bytestream2_get_le32u(gb);
1579  bytestream2_skip(gb, 8);
1580 
1581  if (decoded_size > ctx->aligned_height * width) {
1582  decoded_size = height * width;
1583  av_log(ctx->avctx, AV_LOG_WARNING, "Decoded size is too large.\n");
1584  }
1585 
1586  if (skip & 1) {
1587  if (bytestream2_get_bytes_left(gb) < 0x8080)
1588  return AVERROR_INVALIDDATA;
1589  codec47_read_interptable(gb, ctx->c47itbl);
1590  }
1591  if (!seq) {
1592  ctx->prev_seq = -1;
1593  memset(prev1, auxcol[0], ctx->frm0_size);
1594  memset(prev2, auxcol[1], ctx->frm0_size);
1595  }
1596 
1597  switch (compr) {
1598  case 0:
1600  return AVERROR_INVALIDDATA;
1602  break;
1603  case 1:
1604  if (bytestream2_get_bytes_left(gb) < ((width + 1) >> 1) * ((height + 1) >> 1))
1605  return AVERROR_INVALIDDATA;
1606  codec47_comp1(gb, dst, width, height, width, ctx->c47itbl);
1607  break;
1608  case 2:
1609  if (seq == ctx->prev_seq + 1) {
1610  for (j = 0; j < height; j += 8) {
1611  for (i = 0; i < width; i += 8)
1612  if (codec47_block(ctx, gb, dst + i, prev1 + i, prev2 + i, width, 8))
1613  return AVERROR_INVALIDDATA;
1614  dst += width * 8;
1615  prev1 += width * 8;
1616  prev2 += width * 8;
1617  }
1618  }
1619  break;
1620  case 3:
1621  memcpy(ctx->frm0, ctx->frm2, ctx->frm0_size);
1622  break;
1623  case 4:
1624  memcpy(ctx->frm0, ctx->frm1, ctx->frm0_size);
1625  break;
1626  case 5:
1627  if (rle_decode(ctx, gb, dst, decoded_size))
1628  return AVERROR_INVALIDDATA;
1629  break;
1630  default:
1632  "Subcodec 47 compression %d", compr);
1633  return AVERROR_PATCHWELCOME;
1634  }
1635 
1636  blt_solid((uint8_t*)ctx->fbuf, (uint8_t*)ctx->frm0, left, top, 0, 0, width,
1637  height, width, ctx->pitch, ctx->height, width * height);
1638 
1639  if ((seq == ctx->prev_seq + 1) && new_rot)
1640  rotate_bufs(ctx, new_rot);
1641 
1642  ctx->prev_seq = seq;
1643 
1644  return 0;
1645 }
1646 
1647 // scale 4x4 input block to an 8x8 output block
1648 static void c48_4to8(uint8_t *dst, const uint8_t *src, const uint16_t w)
1649 {
1650  uint16_t p;
1651  // dst is always at least 16bit aligned
1652  for (int i = 0; i < 4; i++) {
1653  for (int j = 0; j < 8; j += 2) {
1654  p = *src++;
1655  p = (p << 8) | p;
1656  *((uint16_t *)(dst + w * 0 + j)) = p;
1657  *((uint16_t *)(dst + w * 1 + j)) = p;
1658  }
1659  dst += w * 2;
1660  }
1661 }
1662 
1663 static int c48_invalid_mv(int x, int y, const uint16_t w, int h, int blocksize, int mvofs) {
1664  if (mvofs < -x + -y*w)
1665  return AVERROR_INVALIDDATA;
1666 
1667  if (mvofs > w-x-blocksize + w*(h-y-blocksize))
1668  return AVERROR_INVALIDDATA;
1669 
1670  return 0;
1671 }
1672 
1673 static int codec48_block(GetByteContext *gb, uint8_t *dst, uint8_t *db, int x, int y,
1674  const uint16_t w, const int aligned_height, const uint8_t *itbl)
1675 {
1676  uint8_t opc, sb[16];
1677  int i, j, k, l;
1678  int16_t mvofs;
1679  uint32_t ofs;
1680 
1681  if (bytestream2_get_bytes_left(gb) < 1)
1682  return 1;
1683 
1684  opc = bytestream2_get_byteu(gb);
1685  switch (opc) {
1686  case 0xFF: // 1x1 -> 8x8 block scale
1687  if (bytestream2_get_bytes_left(gb) < 1)
1688  return 1;
1689 
1690  if (y > 0 && x > 0) {
1691  sb[15] = bytestream2_get_byteu(gb);
1692  sb[ 7] = itbl[(*(dst - 1*w + 7) << 8) | sb[15]];
1693  sb[ 3] = itbl[(*(dst - 1*w + 7) << 8) | sb[ 7]];
1694  sb[11] = itbl[(sb[15] << 8) | sb[ 7]];
1695  sb[ 1] = itbl[(*(dst + 0*w - 1) << 8) | sb[ 3]];
1696  sb[ 0] = itbl[(*(dst + 0*w - 1) << 8) | sb[ 1]];
1697  sb[ 2] = itbl[(sb[ 3] << 8) | sb[ 1]];
1698  sb[ 5] = itbl[(*(dst + 2*w - 1) << 8) | sb[ 7]];
1699  sb[ 4] = itbl[(*(dst + 2*w - 1) << 8) | sb[ 5]];
1700  sb[ 6] = itbl[(sb[ 7] << 8) | sb[ 5]];
1701  sb[ 9] = itbl[(*(dst + 3*w - 1) << 8) | sb[11]];
1702  sb[ 8] = itbl[(*(dst + 3*w - 1) << 8) | sb[ 9]];
1703  sb[10] = itbl[(sb[11] << 8) | sb[ 9]];
1704  sb[13] = itbl[(*(dst + 4*w - 1) << 8) | sb[15]];
1705  sb[12] = itbl[(*(dst + 4*w - 1) << 8) | sb[13]];
1706  sb[14] = itbl[(sb[15] << 8) | sb[13]];
1707  } else {
1708  opc = bytestream2_get_byteu(gb);
1709  for (i = 0; i < 16; i++)
1710  sb[i] = opc;
1711  }
1712  c48_4to8(dst, sb, w);
1713  break;
1714  case 0xFE: // 1x 8x8 copy from deltabuf, 16bit mv from source
1715  if (bytestream2_get_bytes_left(gb) < 2)
1716  return 1;
1717  mvofs = bytestream2_get_le16(gb);
1718  if (c48_invalid_mv(x, y, w, aligned_height, 8, mvofs))
1719  break;
1720  for (i = 0; i < 8; i++) {
1721  ofs = w * i;
1722  for (k = 0; k < 8; k++)
1723  *(dst + ofs + k) = *(db + ofs + k + mvofs);
1724  }
1725  break;
1726  case 0xFD: // 2x2 -> 8x8 block scale
1727  if (bytestream2_get_bytes_left(gb) < 4)
1728  return 1;
1729  sb[ 5] = bytestream2_get_byteu(gb);
1730  sb[ 7] = bytestream2_get_byteu(gb);
1731  sb[13] = bytestream2_get_byteu(gb);
1732  sb[15] = bytestream2_get_byteu(gb);
1733 
1734  if (y > 0 && x >0) {
1735  sb[ 1] = itbl[(*(dst - 1*w + 3) << 8) | sb[ 5]];
1736  sb[ 3] = itbl[(*(dst - 1*w + 7) << 8) | sb[ 7]];
1737  sb[ 9] = itbl[(sb[13] << 8) | sb[ 5]];
1738  sb[11] = itbl[(sb[15] << 8) | sb[ 7]];
1739  sb[ 0] = itbl[(*(dst + 0*w - 1) << 8) | sb[ 1]];
1740  sb[ 2] = itbl[(sb[ 3] << 8) | sb[ 1]];
1741  sb[ 4] = itbl[(*(dst + 2*w - 1) << 8) | sb[ 5]];
1742  sb[ 6] = itbl[(sb[ 7] << 8) | sb[ 5]];
1743  sb[ 8] = itbl[(*(dst + 3*w - 1) << 8) | sb[ 9]];
1744  sb[10] = itbl[(sb[11] << 8) | sb[ 9]];
1745  sb[12] = itbl[(*(dst + 4*w - 1) << 8) | sb[13]];
1746  sb[14] = itbl[(sb[15] << 8) | sb[13]];
1747  } else {
1748  sb[ 0] = sb[ 1] = sb[ 4] = sb[ 5];
1749  sb[ 2] = sb[ 3] = sb[ 6] = sb[ 7];
1750  sb[ 8] = sb[ 9] = sb[12] = sb[13];
1751  sb[10] = sb[11] = sb[14] = sb[15];
1752  }
1753  c48_4to8(dst, sb, w);
1754  break;
1755  case 0xFC: // 4x copy 4x4 block, per-block c37_mv from source
1756  if (bytestream2_get_bytes_left(gb) < 4)
1757  return 1;
1758  for (i = 0; i < 8; i += 4) {
1759  for (k = 0; k < 8; k += 4) {
1760  opc = bytestream2_get_byteu(gb);
1761  mvofs = c37_mv[opc * 2] + (c37_mv[opc * 2 + 1] * w);
1762  if (c48_invalid_mv(x+k, y+i, w, aligned_height, 4, mvofs))
1763  continue;
1764  for (j = 0; j < 4; j++) {
1765  ofs = (w * (j + i)) + k;
1766  for (l = 0; l < 4; l++)
1767  *(dst + ofs + l) = *(db + ofs + l + mvofs);
1768  }
1769  }
1770  }
1771  break;
1772  case 0xFB: // Copy 4x 4x4 blocks, per-block mv from source
1773  if (bytestream2_get_bytes_left(gb) < 8)
1774  return 1;
1775  for (i = 0; i < 8; i += 4) {
1776  for (k = 0; k < 8; k += 4) {
1777  mvofs = bytestream2_get_le16(gb);
1778  if (c48_invalid_mv(x+k, y+i, w, aligned_height, 4, mvofs))
1779  continue;
1780  for (j = 0; j < 4; j++) {
1781  ofs = (w * (j + i)) + k;
1782  for (l = 0; l < 4; l++)
1783  *(dst + ofs + l) = *(db + ofs + l + mvofs);
1784  }
1785  }
1786  }
1787  break;
1788  case 0xFA: // scale 4x4 input block to 8x8 dest block
1789  if (bytestream2_get_bytes_left(gb) < 16)
1790  return 1;
1791  bytestream2_get_bufferu(gb, sb, 16);
1792  c48_4to8(dst, sb, w);
1793  break;
1794  case 0xF9: // 16x 2x2 copy from delta, per-block c37_mv from source
1795  if (bytestream2_get_bytes_left(gb) < 16)
1796  return 1;
1797  for (i = 0; i < 8; i += 2) {
1798  for (j = 0; j < 8; j += 2) {
1799  ofs = (w * i) + j;
1800  opc = bytestream2_get_byteu(gb);
1801  mvofs = c37_mv[opc * 2] + (c37_mv[opc * 2 + 1] * w);
1802  if (c48_invalid_mv(x+j, y+i, w, aligned_height, 2, mvofs))
1803  continue;
1804  for (l = 0; l < 2; l++) {
1805  *(dst + ofs + l + 0) = *(db + ofs + l + 0 + mvofs);
1806  *(dst + ofs + l + w) = *(db + ofs + l + w + mvofs);
1807  }
1808  }
1809  }
1810  break;
1811  case 0xF8: // 16x 2x2 blocks copy, 16bit mv from source
1812  if (bytestream2_get_bytes_left(gb) < 32)
1813  return 1;
1814  for (i = 0; i < 8; i += 2) {
1815  for (j = 0; j < 8; j += 2) {
1816  ofs = w * i + j;
1817  mvofs = bytestream2_get_le16(gb);
1818  if (c48_invalid_mv(x+j, y+i, w, aligned_height, 2, mvofs))
1819  continue;
1820  for (l = 0; l < 2; l++) {
1821  *(dst + ofs + l + 0) = *(db + ofs + l + 0 + mvofs);
1822  *(dst + ofs + l + w) = *(db + ofs + l + w + mvofs);
1823  }
1824  }
1825  }
1826  break;
1827  case 0xF7: // copy 8x8 block from src to dest
1828  if (bytestream2_get_bytes_left(gb) < 64)
1829  return 1;
1830  for (i = 0; i < 8; i++) {
1831  ofs = i * w;
1832  for (l = 0; l < 8; l++)
1833  *(dst + ofs + l) = bytestream2_get_byteu(gb);
1834  }
1835  break;
1836  default: // copy 8x8 block from prev, c37_mv from source
1837  mvofs = c37_mv[opc * 2] + (c37_mv[opc * 2 + 1] * w);
1838  if (c48_invalid_mv(x, y, w, aligned_height, 8, mvofs))
1839  break;
1840  for (i = 0; i < 8; i++) {
1841  ofs = i * w;
1842  for (l = 0; l < 8; l++)
1843  *(dst + ofs + l) = *(db + ofs + l + mvofs);
1844  }
1845  break;
1846  }
1847  return 0;
1848 }
1849 
1850 static int old_codec48(SANMVideoContext *ctx, GetByteContext *gb, int top, int left,
1851  int width, int height)
1852 {
1853  uint8_t *dst, *prev;
1854  int i, j, flags, ah;
1855 
1856  width = FFALIGN(width, 8);
1857  if (width > ctx->aligned_width)
1858  return AVERROR_INVALIDDATA;
1859 
1860  ah = FFALIGN(height, 8);
1861  if (ah > ctx->aligned_height)
1862  return AVERROR_INVALIDDATA;
1863 
1864  if (bytestream2_get_bytes_left(gb) < 16)
1865  return AVERROR_INVALIDDATA;
1866 
1867  int compr = bytestream2_get_byteu(gb);
1868  int mvidx = bytestream2_get_byteu(gb);
1869  int seq = bytestream2_get_le16u(gb);
1870  uint32_t decoded_size = bytestream2_get_le32u(gb);
1871 
1872  // all codec48 videos use 1, but just to be safe...
1873  if (mvidx != 1) {
1874  av_log(ctx->avctx, AV_LOG_ERROR, "Invalid motion base value %d.\n", mvidx);
1875  return AVERROR_INVALIDDATA;
1876  }
1877 
1878  bytestream2_skip(gb, 4);
1879  flags = bytestream2_get_byteu(gb);
1880  bytestream2_skip(gb, 3);
1881 
1882  if (flags & 8) {
1883  if (bytestream2_get_bytes_left(gb) < 0x8080)
1884  return AVERROR_INVALIDDATA;
1885  codec47_read_interptable(gb, ctx->c47itbl);
1886  }
1887 
1888  dst = (uint8_t*)ctx->frm0;
1889  prev = (uint8_t*)ctx->frm2;
1890 
1891  if (seq == 0)
1892  memset(ctx->frm2, 0, ctx->frm2_size);
1893 
1894  switch (compr) {
1895  case 0:
1897  return AVERROR_INVALIDDATA;
1899  break;
1900  case 2:
1901  if (decoded_size > width * height) {
1902  av_log(ctx->avctx, AV_LOG_ERROR, "Decoded size %u is too large.\n", decoded_size);
1903  decoded_size = width * height;
1904  }
1905 
1906  if (rle_decode(ctx, gb, dst, decoded_size))
1907  return AVERROR_INVALIDDATA;
1908  break;
1909  case 3:
1910  if ((seq == 0) || (seq == ctx->prev_seq + 1)) {
1911  if ((seq & 1) || ((flags & 1) == 0) || (flags & 0x10)) {
1912  FFSWAP(uint16_t*, ctx->frm0, ctx->frm2);
1913  dst = (uint8_t*)ctx->frm0;
1914  prev = (uint8_t*)ctx->frm2;
1915  }
1916  for (j = 0; j < height; j += 8) {
1917  for (i = 0; i < width; i += 8) {
1918  if (codec48_block(gb, dst + i, prev + i, i, j, width,
1919  ah, ctx->c47itbl))
1920  return AVERROR_INVALIDDATA;
1921  }
1922  dst += width * 8;
1923  prev += width * 8;
1924  }
1925  }
1926  break;
1927  case 5:
1928  if (bytestream2_get_bytes_left(gb) < ((width + 1) >> 1) * ((height + 1) >> 1))
1929  return AVERROR_INVALIDDATA;
1930  codec47_comp1(gb, dst, width, height, width, ctx->c47itbl);
1931  break;
1932  case 6: /* this is a "stub" frame that follows a frame with flag 0x10 set. */
1933  break;
1934  default:
1936  "Subcodec 48 compression %d", compr);
1937  return AVERROR_PATCHWELCOME;
1938  }
1939 
1940  ctx->prev_seq = seq;
1941  if ((flags & 2) == 0) {
1942  if (flags & 0x10) {
1943  /* generate an artificial frame from the 2 buffers. This will be
1944  * followed up immediately with a codec48 compression 6 frame, which
1945  * will then blit the actual decoding result (frm0) to the main buffer.
1946  */
1947  blt_ipol((uint8_t*)ctx->fbuf, (uint8_t*)ctx->frm0, (uint8_t*)ctx->frm2,
1948  left, top, 0, 0, width, height, width, ctx->pitch, ctx->height,
1949  width * height, ctx->c47itbl);
1950  return 0;
1951  }
1952  blt_solid((uint8_t*)ctx->fbuf, (uint8_t*)ctx->frm0, left, top, 0, 0, width,
1953  height, width, ctx->pitch, ctx->height, width * height);
1954  } else {
1955  blt_mask((uint8_t*)ctx->fbuf, (uint8_t*)ctx->frm0, left, top, 0, 0, width,
1956  height, width, ctx->pitch, ctx->height, width * height, 0);
1957  }
1958  return 0;
1959 }
1960 
1961 static void old_codec45(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int flag)
1962 {
1963  int t1, t2, i;
1964 
1965  if (bytestream2_get_bytes_left(gb) < 6)
1966  return;
1967 
1968  bytestream2_skip(gb, 2);
1969  t1 = bytestream2_get_le16u(gb);
1970  t2 = bytestream2_get_byteu(gb);
1971  bytestream2_skip(gb, 1);
1972  if (t2 != 1)
1973  return;
1974  if (t1 == 0) {
1975  if (bytestream2_get_bytes_left(gb) < 0x300)
1976  return;
1977  bytestream2_get_bufferu(gb, ctx->c45tbl1, 0x300);
1978  i = 0;
1979  while ((bytestream2_get_bytes_left(gb) > 1) && (i < 0x8000)) {
1980  uint8_t len = bytestream2_get_byteu(gb);
1981  uint8_t val = bytestream2_get_byteu(gb);
1982  if ((i + len) > 0x8000)
1983  len = 0x8000 - i;
1984  memset(ctx->c45tbl2 + i, val, len);
1985  i += len;
1986  }
1987  }
1988 
1989  if (flag)
1990  return;
1991 
1992  while (bytestream2_get_bytes_left(gb) > 3) {
1993  left += (int16_t)bytestream2_get_le16u(gb);
1994  top += bytestream2_get_byteu(gb);
1995  int len = bytestream2_get_byteu(gb);
1996  while (len >= 0) {
1997  if ((left > 0) && (top > 0) && (left < (ctx->width - 1))) {
1998  if (top >= (ctx->height - 1))
1999  return;
2000 
2001  uint8_t *dst = (uint8_t *)ctx->fbuf + left + top * ctx->pitch;
2002  unsigned int c1 = *(dst - 1) * 3;
2003  unsigned int c2 = *(dst + 1) * 3;
2004  unsigned int r = ctx->c45tbl1[c1 + 0] + ctx->c45tbl1[c2 + 0];
2005  unsigned int g = ctx->c45tbl1[c1 + 1] + ctx->c45tbl1[c2 + 1];
2006  unsigned int b = ctx->c45tbl1[c1 + 2] + ctx->c45tbl1[c2 + 2];
2007  c1 = *(dst - ctx->pitch) * 3;
2008  c2 = *(dst + ctx->pitch) * 3;
2009  r += ctx->c45tbl1[c1 + 0] + ctx->c45tbl1[c2 + 0];
2010  g += ctx->c45tbl1[c1 + 1] + ctx->c45tbl1[c2 + 1];
2011  b += ctx->c45tbl1[c1 + 2] + ctx->c45tbl1[c2 + 2];
2012  *dst = ctx->c45tbl2[((r << 5) & 0x7c00) | (g & 0x3e0) | (b >> 5)];
2013  }
2014  left++;
2015  len--;
2016  }
2017  left--;
2018  }
2019 }
2020 
2022  int xoff, int yoff)
2023 {
2024  uint16_t w, h, parm2;
2025  uint8_t codec, param;
2026  int16_t left, top;
2027  int fsc;
2028 
2029  codec = bytestream2_get_byteu(gb);
2030  param = bytestream2_get_byteu(gb);
2031  left = bytestream2_get_le16u(gb);
2032  top = bytestream2_get_le16u(gb);
2033  w = bytestream2_get_le16u(gb);
2034  h = bytestream2_get_le16u(gb);
2035  bytestream2_skip(gb, 2);
2036  parm2 = bytestream2_get_le16u(gb);
2037 
2038  if (w < 1 || h < 1 || w > 640 || h > 480 || left > 640 || top > 480 || left + w <= 0 || top + h <= 0) {
2039  /* codec45 frames with data for the 2 tables have nonsensical dimensions */
2040  if (codec == 45) {
2041  old_codec45(ctx, gb, 0, 0, 1);
2042  return 0;
2043  }
2044 
2045  av_log(ctx->avctx, AV_LOG_WARNING,
2046  "ignoring invalid fobj dimensions: c%d %d %d @ %d %d\n",
2047  codec, w, h, left, top);
2048  return 0;
2049  }
2050 
2051  /* codecs with their own buffers */
2052  fsc = (codec == 37 || codec == 47 || codec == 48);
2053 
2054  /* special case for "Shadows of the Empire" videos: they have top=60
2055  * at all frames to vertically center the video in the 640x480 game
2056  * window, but we don't need that.
2057  */
2058  if ((w == 640) && (h == 272) && (top == 60) && (codec == 47))
2059  left = top = 0;
2060 
2061  if (!ctx->have_dimensions && (codec != 45)) {
2062  int xres, yres;
2063  if (ctx->subversion < 2) {
2064  /* Rebel Assault 1: 384x242 internal size */
2065  xres = 384;
2066  yres = 242;
2067  if (w > xres || h > yres)
2068  return AVERROR_INVALIDDATA;
2069  ctx->have_dimensions = 1;
2070  } else {
2071  /* detect common sizes */
2072  xres = w + left;
2073  yres = h + top;
2074  if (((xres == 424) && (yres == 260)) || /* RA2 */
2075  ((xres == 320) && (yres == 200)) || /* FT/Dig */
2076  ((xres == 640) && (yres == 272)) || /* SotE */
2077  ((xres == 640) && (yres == 350)) || /* MotS */
2078  ((xres == 640) && (yres == 480))) {
2079  ctx->have_dimensions = 1;
2080  }
2081 
2082  xres = FFMAX(xres, ctx->width);
2083  yres = FFMAX(yres, ctx->height);
2084  }
2085 
2086  if ((xres < (fsc ? 8 : 1)) || (yres < (fsc ? 8 : 1)) || (xres > 640) || (yres > 480))
2087  return AVERROR_INVALIDDATA;
2088 
2089  if (ctx->width < xres || ctx->height < yres) {
2090  int ret = ff_set_dimensions(ctx->avctx, xres, yres);
2091  if (ret < 0)
2092  return ret;
2093  init_sizes(ctx, xres, yres);
2094  if (init_buffers(ctx)) {
2095  av_log(ctx->avctx, AV_LOG_ERROR, "Error resizing buffers.\n");
2096  return AVERROR(ENOMEM);
2097  }
2098  }
2099  } else {
2100  /* for codec37/47/48, return error for frames larger than the canvas, it's also
2101  * what the DOS engines do.
2102  */
2103  if (((w > ctx->width) || (h > ctx->height) || (w * h > ctx->buf_size)) && fsc)
2104  return AVERROR_INVALIDDATA;
2105  }
2106 
2107  /* users of codecs>=37 are subversion 2, enforce that for STOR/FTCH */
2108  if (fsc && ctx->subversion < 2) {
2109  ctx->subversion = 2;
2110  ctx->stor_size = 0; /* invalidate existing data */
2111  }
2112 
2113  /* clear the main buffer on the first fob */
2114  if (ctx->first_fob) {
2115  ctx->first_fob = 0;
2116  if (!fsc)
2117  memset(ctx->fbuf, 0, ctx->frm0_size);
2118  }
2119 
2120  left += xoff;
2121  top += yoff;
2122 
2123  switch (codec) {
2124  case 1:
2125  case 3:
2126  return old_codec1(ctx, gb, top, left, w, h, codec == 3);
2127  case 2:
2128  return old_codec2(ctx, gb, top, left, w, h);
2129  case 4:
2130  case 5:
2131  case 33:
2132  case 34:
2133  return old_codec4(ctx, gb, top, left, w, h, param, parm2, codec);
2134  case 20:
2135  return old_codec20(ctx, gb, top, left, w, h);
2136  case 21:
2137  return old_codec21(ctx, gb, top, left, w, h);
2138  case 23:
2139  return old_codec23(ctx, gb, top, left, w, h, param, parm2);
2140  case 31:
2141  case 32:
2142  return old_codec31(ctx, gb, top, left, w, h, param, (codec == 32));
2143  case 37:
2144  return old_codec37(ctx, gb, top, left, w, h); break;
2145  case 45:
2146  old_codec45(ctx, gb, top, left, 0); break;
2147  case 47:
2148  return old_codec47(ctx, gb, top, left, w, h); break;
2149  case 48:
2150  return old_codec48(ctx, gb, top, left, w, h); break;
2151  default:
2152  avpriv_request_sample(ctx->avctx, "Subcodec %d", codec);
2153  ctx->frame->flags |= AV_FRAME_FLAG_CORRUPT;
2154  break;
2155  }
2156  return 0;
2157 }
2158 
2160 {
2161  int xoff, yoff, ret;
2162  GetByteContext gb;
2163 
2164  /* FTCH defines additional x/y offsets */
2165  if (size == 6) {
2166  bytestream2_skip(&ctx->gb, 2);
2167  xoff = bytestream2_get_le16u(&ctx->gb);
2168  yoff = bytestream2_get_le16u(&ctx->gb);
2169  } else if (size == 12) {
2171  bytestream2_skip(&ctx->gb, 4);
2172  xoff = bytestream2_get_be32u(&ctx->gb);
2173  yoff = bytestream2_get_be32u(&ctx->gb);
2174  } else
2175  return 1;
2176 
2177  if (ctx->stor_size > 0) {
2178  /* decode the stored FOBJ */
2179  uint8_t *bitstream = av_malloc(ctx->stor_size + AV_INPUT_BUFFER_PADDING_SIZE);
2180  if (!bitstream)
2181  return AVERROR(ENOMEM);
2182  memcpy(bitstream, ctx->stored_frame, ctx->stor_size);
2183  bytestream2_init(&gb, bitstream, ctx->stor_size);
2184  ret = process_frame_obj(ctx, &gb, xoff, yoff);
2185  av_free(bitstream);
2186  } else {
2187  /* this happens a lot in RA1: The individual files are meant to
2188  * be played in sequence, with some referencing objects STORed
2189  * by previous files, e.g. the cockpit codec21 object in RA1 LVL8.
2190  * But spamming the log with errors is also not helpful, so
2191  * here we simply ignore this case. Return 1 to indicate that
2192  * there was no valid image fetched.
2193  */
2194  ret = 1;
2195  }
2196  return ret;
2197 }
2198 
2200 {
2201  int16_t *dp = ctx->delta_pal;
2202  uint32_t *pal = ctx->pal;
2203  uint16_t cmd;
2204  uint8_t c[3];
2205  int i, j;
2206 
2207  if (size < 4)
2208  return AVERROR_INVALIDDATA;
2209  bytestream2_skip(&ctx->gb, 2);
2210  cmd = bytestream2_get_be16(&ctx->gb);
2211  size -= 4;
2212 
2213  if (cmd == 1) {
2214  for (i = 0; i < PALETTE_DELTA; i += 3) {
2215  for (j = 0; j < 3; j++) {
2216  ctx->shift_pal[i + j] += dp[i + j];
2217  c[j] = av_clip_uint8(ctx->shift_pal[i + j] >> 7) & 0xFFU;
2218  }
2219  *pal++ = 0xFFU << 24 | c[0] << 16 | c[1] << 8 | c[2];
2220  }
2221  } else if (cmd == 0 || cmd == 2) {
2222  if (size < PALETTE_DELTA * 2) {
2223  av_log(ctx->avctx, AV_LOG_ERROR,
2224  "Incorrect palette change block size %"PRIu32".\n", size);
2225  return AVERROR_INVALIDDATA;
2226  }
2227  for (i = 0; i < PALETTE_DELTA; i++)
2228  dp[i] = bytestream2_get_le16u(&ctx->gb);
2229  size -= PALETTE_DELTA * 2;
2230 
2231  if (size >= PALETTE_SIZE * 3) {
2232  for (i = 0; i < PALETTE_SIZE; i++)
2233  ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb);
2234  if (ctx->subversion < 2)
2235  ctx->pal[0] = 0xFFU << 24;
2236  }
2237  for (i = 0, j = 0; i < PALETTE_DELTA; i += 3, j++) {
2238  ctx->shift_pal[i + 0] = (((ctx->pal[j]) >> 16) & 0xFFU) << 7;
2239  ctx->shift_pal[i + 1] = (((ctx->pal[j]) >> 8) & 0xFFU) << 7;
2240  ctx->shift_pal[i + 2] = (((ctx->pal[j]) >> 0) & 0xFFU) << 7;
2241  }
2242  }
2243  return 0;
2244 }
2245 
2247 {
2248  uint16_t *frm = ctx->frm0;
2249  int x, y;
2250 
2251  if (bytestream2_get_bytes_left(&ctx->gb) < ctx->width * ctx->height * 2) {
2252  av_log(ctx->avctx, AV_LOG_ERROR, "Insufficient data for raw frame.\n");
2253  return AVERROR_INVALIDDATA;
2254  }
2255  for (y = 0; y < ctx->height; y++) {
2256  for (x = 0; x < ctx->width; x++)
2257  frm[x] = bytestream2_get_le16u(&ctx->gb);
2258  frm += ctx->pitch;
2259  }
2260  return 0;
2261 }
2262 
2263 /* BL16 pixel interpolation function, see tgsmush.dll c690 */
2264 static inline uint16_t bl16_c1_avg_col(uint16_t c1, uint16_t c2)
2265 {
2266  return (((c2 & 0x07e0) + (c1 & 0x07e0)) & 0x00fc0) |
2267  (((c2 & 0xf800) + (c1 & 0xf800)) & 0x1f000) |
2268  (((c2 & 0x001f) + (c1 & 0x001f))) >> 1;
2269 }
2270 
2271 /* Quarter-sized keyframe encoded as stream of 16bit pixel values. Interpolate
2272  * missing pixels by averaging the colors of immediate neighbours.
2273  * Identical to codec47_comp1() but with 16bit-pixels. tgsmush.dll c6f0
2274  */
2276 {
2277  uint16_t hh, hw, hw1, c1, c2, *dst1, *dst2;
2278 
2279  hh = (ctx->height + 1) >> 1;
2280  hw1 = (ctx->width - 1) >> 1;
2281  if (!hw1 || (bytestream2_get_bytes_left(&ctx->gb) < (hh * hw1 * 2)))
2282  return AVERROR_INVALIDDATA;
2283  dst1 = (uint16_t *)ctx->frm0 + ctx->pitch; /* start with line 1 */
2284  while (hh--) {
2285  hw = hw1;
2286  c1 = bytestream2_get_le16u(&ctx->gb);
2287  dst1[0] = c1;
2288  dst1[1] = c1;
2289  dst2 = dst1 + 2;
2290  while (--hw) {
2291  c2 = bytestream2_get_le16u(&ctx->gb);
2292  *dst2++ = bl16_c1_avg_col(c1, c2);
2293  *dst2++ = c2;
2294  c1 = c2;
2295  }
2296  dst1 += ctx->pitch * 2; /* skip to overnext line */
2297  }
2298  /* line 0 is a copy of line 1 */
2299  memcpy(ctx->frm0, ctx->frm0 + ctx->pitch, ctx->pitch);
2300 
2301  /* complete the skipped lines by averaging from the pixels in the lines
2302  * above and below
2303  */
2304  dst1 = ctx->frm0 + (ctx->pitch * 2);
2305  hh = (ctx->height - 1) >> 1;
2306  while (hh--) {
2307  hw = ctx->width;
2308  dst2 = dst1;
2309  while (hw--) {
2310  c1 = *(dst2 - ctx->pitch); /* pixel from line above */
2311  c2 = *(dst2 + ctx->pitch); /* pixel from line below */
2312  *dst2++ = bl16_c1_avg_col(c1, c2);
2313  }
2314  dst1 += ctx->pitch * 2;
2315  }
2316  return 0;
2317 }
2318 
2319 static void copy_block(uint16_t *pdest, uint16_t *psrc, int block_size, ptrdiff_t pitch)
2320 {
2321  uint8_t *dst = (uint8_t *)pdest;
2322  uint8_t *src = (uint8_t *)psrc;
2323  ptrdiff_t stride = pitch * 2;
2324 
2325  switch (block_size) {
2326  case 2:
2327  copy_block4(dst, src, stride, stride, 2);
2328  break;
2329  case 4:
2330  copy_block8(dst, src, stride, stride, 4);
2331  break;
2332  case 8:
2333  copy_block16(dst, src, stride, stride, 8);
2334  break;
2335  }
2336 }
2337 
2338 static void fill_block(uint16_t *pdest, uint16_t color, int block_size, ptrdiff_t pitch)
2339 {
2340  int x, y;
2341 
2342  pitch -= block_size;
2343  for (y = 0; y < block_size; y++, pdest += pitch)
2344  for (x = 0; x < block_size; x++)
2345  *pdest++ = color;
2346 }
2347 
2348 static int draw_glyph(SANMVideoContext *ctx, uint16_t *dst, int index,
2349  uint16_t fg_color, uint16_t bg_color, int block_size,
2350  ptrdiff_t pitch)
2351 {
2352  int8_t *pglyph;
2353  uint16_t colors[2] = { fg_color, bg_color };
2354  int x, y;
2355 
2356  if (index >= NGLYPHS) {
2357  av_log(ctx->avctx, AV_LOG_ERROR, "Ignoring nonexistent glyph #%u.\n", index);
2358  return AVERROR_INVALIDDATA;
2359  }
2360 
2361  pglyph = block_size == 8 ? ctx->p8x8glyphs[index] : ctx->p4x4glyphs[index];
2362  pitch -= block_size;
2363 
2364  for (y = 0; y < block_size; y++, dst += pitch)
2365  for (x = 0; x < block_size; x++)
2366  *dst++ = colors[*pglyph++];
2367  return 0;
2368 }
2369 
2370 static int opcode_0xf7(SANMVideoContext *ctx, int cx, int cy, int block_size, ptrdiff_t pitch)
2371 {
2372  uint16_t *dst = ctx->frm0 + cx + cy * ctx->pitch;
2373 
2374  if (block_size == 2) {
2375  uint32_t indices;
2376 
2377  if (bytestream2_get_bytes_left(&ctx->gb) < 4)
2378  return AVERROR_INVALIDDATA;
2379 
2380  indices = bytestream2_get_le32u(&ctx->gb);
2381  dst[0] = ctx->codebook[indices & 0xFF];
2382  indices >>= 8;
2383  dst[1] = ctx->codebook[indices & 0xFF];
2384  indices >>= 8;
2385  dst[pitch] = ctx->codebook[indices & 0xFF];
2386  indices >>= 8;
2387  dst[pitch + 1] = ctx->codebook[indices & 0xFF];
2388  } else {
2389  uint16_t fgcolor, bgcolor;
2390  int glyph;
2391 
2392  if (bytestream2_get_bytes_left(&ctx->gb) < 3)
2393  return AVERROR_INVALIDDATA;
2394 
2395  glyph = bytestream2_get_byteu(&ctx->gb);
2396  bgcolor = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
2397  fgcolor = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
2398 
2399  draw_glyph(ctx, dst, glyph, fgcolor, bgcolor, block_size, pitch);
2400  }
2401  return 0;
2402 }
2403 
2404 static int opcode_0xf8(SANMVideoContext *ctx, int cx, int cy, int block_size, ptrdiff_t pitch)
2405 {
2406  uint16_t *dst = ctx->frm0 + cx + cy * ctx->pitch;
2407 
2408  if (block_size == 2) {
2409  if (bytestream2_get_bytes_left(&ctx->gb) < 8)
2410  return AVERROR_INVALIDDATA;
2411 
2412  dst[0] = bytestream2_get_le16u(&ctx->gb);
2413  dst[1] = bytestream2_get_le16u(&ctx->gb);
2414  dst[pitch] = bytestream2_get_le16u(&ctx->gb);
2415  dst[pitch + 1] = bytestream2_get_le16u(&ctx->gb);
2416  } else {
2417  uint16_t fgcolor, bgcolor;
2418  int glyph;
2419 
2420  if (bytestream2_get_bytes_left(&ctx->gb) < 5)
2421  return AVERROR_INVALIDDATA;
2422 
2423  glyph = bytestream2_get_byteu(&ctx->gb);
2424  bgcolor = bytestream2_get_le16u(&ctx->gb);
2425  fgcolor = bytestream2_get_le16u(&ctx->gb);
2426 
2427  draw_glyph(ctx, dst, glyph, fgcolor, bgcolor, block_size, pitch);
2428  }
2429  return 0;
2430 }
2431 
2432 static int good_mvec(SANMVideoContext *ctx, int cx, int cy, int mx, int my,
2433  int block_size)
2434 {
2435  int start_pos = cx + mx + (cy + my) * ctx->pitch;
2436  int end_pos = start_pos + (block_size - 1) * (ctx->pitch + 1);
2437 
2438  int good = start_pos >= 0 && end_pos < (ctx->buf_size >> 1);
2439 
2440  if (!good)
2441  av_log(ctx->avctx, AV_LOG_ERROR,
2442  "Ignoring invalid motion vector (%i, %i)->(%u, %u), block size = %u\n",
2443  cx + mx, cy + my, cx, cy, block_size);
2444 
2445  return good;
2446 }
2447 
2448 static int bl16_block(SANMVideoContext *ctx, int cx, int cy, int blk_size)
2449 {
2450  int16_t mx, my, index;
2451  int opcode;
2452 
2453  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
2454  return AVERROR_INVALIDDATA;
2455 
2456  opcode = bytestream2_get_byteu(&ctx->gb);
2457 
2458  switch (opcode) {
2459  default:
2460  mx = c47_mv[opcode][0];
2461  my = c47_mv[opcode][1];
2462 
2463  /* The original implementation of this codec precomputes a table
2464  * of int16_t of all motion vectors a for given image width.
2465  * For widths starting at 762 pixels, the calculation of
2466  * mv table indices 1+ and 255- overflow the int16_t, inverting the
2467  * sign of the offset. This is actively exploited in e.g. the
2468  * "jonesopn_8.snm" video of "Indiana Jones and the Infernal Machine".
2469  * Therefore let the overflow happen and extract x/y components from
2470  * the new value.
2471  */
2472  if (ctx->width > 761) {
2473  index = (int16_t)(my * ctx->width + mx);
2474  mx = index % ctx->width;
2475  my = index / ctx->width;
2476  }
2477  if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
2478  copy_block(ctx->frm0 + cx + ctx->pitch * cy,
2479  ctx->frm2 + cx + mx + ctx->pitch * (cy + my),
2480  blk_size, ctx->pitch);
2481  }
2482  break;
2483  case 0xF5:
2484  if (bytestream2_get_bytes_left(&ctx->gb) < 2)
2485  return AVERROR_INVALIDDATA;
2486  index = bytestream2_get_le16u(&ctx->gb);
2487 
2488  mx = index % ctx->width;
2489  my = index / ctx->width;
2490 
2491  if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
2492  copy_block(ctx->frm0 + cx + ctx->pitch * cy,
2493  ctx->frm2 + cx + mx + ctx->pitch * (cy + my),
2494  blk_size, ctx->pitch);
2495  }
2496  break;
2497  case 0xF6:
2498  copy_block(ctx->frm0 + cx + ctx->pitch * cy,
2499  ctx->frm1 + cx + ctx->pitch * cy,
2500  blk_size, ctx->pitch);
2501  break;
2502  case 0xF7:
2503  opcode_0xf7(ctx, cx, cy, blk_size, ctx->pitch);
2504  break;
2505 
2506  case 0xF8:
2507  opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch);
2508  break;
2509  case 0xF9:
2510  case 0xFA:
2511  case 0xFB:
2512  case 0xFC:
2513  fill_block(ctx->frm0 + cx + cy * ctx->pitch,
2514  ctx->small_codebook[opcode - 0xf9], blk_size, ctx->pitch);
2515  break;
2516  case 0xFD:
2517  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
2518  return AVERROR_INVALIDDATA;
2519  fill_block(ctx->frm0 + cx + cy * ctx->pitch,
2520  ctx->codebook[bytestream2_get_byteu(&ctx->gb)], blk_size, ctx->pitch);
2521  break;
2522  case 0xFE:
2523  if (bytestream2_get_bytes_left(&ctx->gb) < 2)
2524  return AVERROR_INVALIDDATA;
2525  fill_block(ctx->frm0 + cx + cy * ctx->pitch,
2526  bytestream2_get_le16u(&ctx->gb), blk_size, ctx->pitch);
2527  break;
2528  case 0xFF:
2529  if (blk_size == 2) {
2530  opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch);
2531  } else {
2532  blk_size >>= 1;
2533  if (bl16_block(ctx, cx, cy, blk_size))
2534  return AVERROR_INVALIDDATA;
2535  if (bl16_block(ctx, cx + blk_size, cy, blk_size))
2536  return AVERROR_INVALIDDATA;
2537  if (bl16_block(ctx, cx, cy + blk_size, blk_size))
2538  return AVERROR_INVALIDDATA;
2539  if (bl16_block(ctx, cx + blk_size, cy + blk_size, blk_size))
2540  return AVERROR_INVALIDDATA;
2541  }
2542  break;
2543  }
2544  return 0;
2545 }
2546 
2548 {
2549  int cx, cy, ret;
2550 
2551  for (cy = 0; cy < ctx->aligned_height; cy += 8)
2552  for (cx = 0; cx < ctx->aligned_width; cx += 8)
2553  if (ret = bl16_block(ctx, cx, cy, 8))
2554  return ret;
2555 
2556  return 0;
2557 }
2558 
2559 static int bl16_decode_5(SANMVideoContext *ctx, int rle_size)
2560 {
2561 #if HAVE_BIGENDIAN
2562  uint16_t *frm;
2563  int npixels;
2564 #endif
2565  uint8_t *dst = (uint8_t*)ctx->frm0;
2566 
2567  if (rle_decode(ctx, &ctx->gb, dst, rle_size))
2568  return AVERROR_INVALIDDATA;
2569 
2570 #if HAVE_BIGENDIAN
2571  npixels = ctx->npixels;
2572  frm = ctx->frm0;
2573  while (npixels--) {
2574  *frm = av_bswap16(*frm);
2575  frm++;
2576  }
2577 #endif
2578 
2579  return 0;
2580 }
2581 
2583 {
2584  int npixels = ctx->npixels;
2585  uint16_t *frm = ctx->frm0;
2586 
2587  if (bytestream2_get_bytes_left(&ctx->gb) < npixels) {
2588  av_log(ctx->avctx, AV_LOG_ERROR, "Insufficient data for frame.\n");
2589  return AVERROR_INVALIDDATA;
2590  }
2591  while (npixels--)
2592  *frm++ = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
2593 
2594  return 0;
2595 }
2596 
2597 /* Quarter-sized keyframe encoded as stream of codebook indices. Interpolate
2598  * missing pixels by averaging the colors of immediate neighbours.
2599  * Identical to codec47_comp1(), but without the interpolation table.
2600  * tgsmush.dll c6f0
2601  */
2603 {
2604  uint16_t hh, hw, hw1, c1, c2, *dst1, *dst2;
2605 
2606  hh = (ctx->height + 1) >> 1;
2607  hw1 = (ctx->width - 1) >> 1;
2608  if (!hw1 || (bytestream2_get_bytes_left(&ctx->gb) < (hh * hw1)))
2609  return AVERROR_INVALIDDATA;
2610  dst1 = (uint16_t *)ctx->frm0 + ctx->pitch; /* start with line 1 */
2611  while (hh--) {
2612  hw = hw1;
2613  c1 = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
2614  dst1[0] = c1; /* leftmost 2 pixels of a row are identical */
2615  dst1[1] = c1;
2616  dst2 = dst1 + 2;
2617  while (--hw) {
2618  c2 = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
2619  *dst2++ = bl16_c1_avg_col(c1, c2);
2620  *dst2++ = c2;
2621  c1 = c2;
2622  }
2623  dst1 += ctx->pitch * 2; /* skip to overnext line */
2624  }
2625  /* line 0 is a copy of line 1 */
2626  memcpy(ctx->frm0, ctx->frm0 + ctx->pitch, ctx->pitch);
2627 
2628  /* complete the skipped lines by averaging from the pixels in the lines
2629  * above and below.
2630  */
2631  dst1 = ctx->frm0 + (ctx->pitch * 2);
2632  hh = (ctx->height - 1) >> 1;
2633  while (hh--) {
2634  hw = ctx->width;
2635  dst2 = dst1;
2636  while (hw--) {
2637  c1 = *(dst2 - ctx->pitch); /* pixel from line above */
2638  c2 = *(dst2 + ctx->pitch); /* pixel from line below */
2639  *dst2++ = bl16_c1_avg_col(c1, c2);
2640  }
2641  dst1 += ctx->pitch * 2;
2642  }
2643  return 0;
2644 }
2645 
2647 {
2648  uint16_t *pdest = ctx->frm0;
2649  uint8_t *rsrc;
2650  long npixels = ctx->npixels;
2651 
2652  av_fast_malloc(&ctx->rle_buf, &ctx->rle_buf_size, npixels);
2653  if (!ctx->rle_buf) {
2654  av_log(ctx->avctx, AV_LOG_ERROR, "RLE buffer allocation failed.\n");
2655  return AVERROR(ENOMEM);
2656  }
2657  rsrc = ctx->rle_buf;
2658 
2659  if (rle_decode(ctx, &ctx->gb, rsrc, npixels))
2660  return AVERROR_INVALIDDATA;
2661 
2662  while (npixels--)
2663  *pdest++ = ctx->codebook[*rsrc++];
2664 
2665  return 0;
2666 }
2667 
2668 static void fill_frame(uint16_t *pbuf, int buf_size, uint16_t color)
2669 {
2670  if (buf_size--) {
2671  *pbuf++ = color;
2672  av_memcpy_backptr((uint8_t*)pbuf, 2, 2*buf_size);
2673  }
2674 }
2675 
2676 static int copy_output(SANMVideoContext *ctx, int sanm)
2677 {
2678  uint8_t *dst;
2679  const uint8_t *src = sanm ? (uint8_t *)ctx->frm0 : (uint8_t *)ctx->fbuf;
2680  int ret, height = ctx->height;
2681  ptrdiff_t dstpitch, srcpitch = ctx->pitch * (sanm ? sizeof(ctx->frm0[0]) : 1);
2682 
2683  if ((ret = ff_get_buffer(ctx->avctx, ctx->frame, 0)) < 0)
2684  return ret;
2685 
2686  dst = ctx->frame->data[0];
2687  dstpitch = ctx->frame->linesize[0];
2688 
2689  while (height--) {
2690  memcpy(dst, src, srcpitch);
2691  src += srcpitch;
2692  dst += dstpitch;
2693  }
2694 
2695  return 0;
2696 }
2697 
2698 static int decode_bl16(AVCodecContext *avctx,int *got_frame_ptr)
2699 {
2700  SANMVideoContext *ctx = avctx->priv_data;
2701  int i, ret, w, h, seq_num, codec, bg_color, rle_output_size, rcode;
2702 
2703  if ((ret = bytestream2_get_bytes_left(&ctx->gb)) < 560) {
2704  av_log(ctx->avctx, AV_LOG_ERROR, "Input frame too short (%d bytes).\n",
2705  ret);
2706  return AVERROR_INVALIDDATA;
2707  }
2708  bytestream2_skip(&ctx->gb, 8); // skip pad
2709 
2710  w = bytestream2_get_le32u(&ctx->gb);
2711  h = bytestream2_get_le32u(&ctx->gb);
2712 
2713  if (w != ctx->width || h != ctx->height) {
2714  avpriv_report_missing_feature(ctx->avctx, "Variable size frames");
2715  return AVERROR_PATCHWELCOME;
2716  }
2717 
2718  seq_num = bytestream2_get_le16u(&ctx->gb);
2719  codec = bytestream2_get_byteu(&ctx->gb);
2720  rcode = bytestream2_get_byteu(&ctx->gb);
2721 
2722  bytestream2_skip(&ctx->gb, 4); // skip pad
2723 
2724  for (i = 0; i < 4; i++)
2725  ctx->small_codebook[i] = bytestream2_get_le16u(&ctx->gb);
2726  bg_color = bytestream2_get_le16u(&ctx->gb);
2727 
2728  bytestream2_skip(&ctx->gb, 2); // skip pad
2729 
2730  rle_output_size = bytestream2_get_le32u(&ctx->gb);
2731  if (rle_output_size > w * ctx->aligned_height * 2) {
2732  av_log(avctx, AV_LOG_WARNING, "bl16 rle size too large, truncated: %d\n",
2733  rle_output_size);
2734  rle_output_size = w * ctx->aligned_height * 2;
2735  }
2736 
2737  for (i = 0; i < 256; i++)
2738  ctx->codebook[i] = bytestream2_get_le16u(&ctx->gb);
2739 
2740  bytestream2_skip(&ctx->gb, 8); // skip pad
2741 
2742  if (seq_num == 0) {
2743  ctx->frame->flags |= AV_FRAME_FLAG_KEY;
2744  ctx->frame->pict_type = AV_PICTURE_TYPE_I;
2745  fill_frame(ctx->frm1, ctx->npixels, bg_color);
2746  fill_frame(ctx->frm2, ctx->npixels, bg_color);
2747  } else {
2748  ctx->frame->flags &= ~AV_FRAME_FLAG_KEY;
2749  ctx->frame->pict_type = AV_PICTURE_TYPE_P;
2750  }
2751 
2752  ret = 0;
2753  switch (codec) {
2754  case 0: ret = bl16_decode_0(ctx); break;
2755  case 1: ret = bl16_decode_1(ctx); break;
2756  case 2: ret = bl16_decode_2(ctx); break;
2757  case 3: memcpy(ctx->frm0, ctx->frm2, ctx->frm2_size); break;
2758  case 4: memcpy(ctx->frm0, ctx->frm1, ctx->frm1_size); break;
2759  case 5: ret = bl16_decode_5(ctx, rle_output_size); break;
2760  case 6: ret = bl16_decode_6(ctx); break;
2761  case 7: ret = bl16_decode_7(ctx); break;
2762  case 8: ret = bl16_decode_8(ctx); break;
2763  default:
2764  avpriv_request_sample(ctx->avctx, "Unknown/unsupported compression type %d", codec);
2765  return AVERROR_PATCHWELCOME;
2766  }
2767 
2768  if (ret) {
2769  av_log(avctx, AV_LOG_ERROR,
2770  "Subcodec %d: error decoding frame.\n", codec);
2771  return ret;
2772  }
2773 
2774  ret = copy_output(ctx, 1);
2775  if (rcode)
2776  rotate_bufs(ctx, rcode);
2777  if (ret)
2778  return ret;
2779 
2780  *got_frame_ptr = 1;
2781  return 0;
2782 }
2783 
2784 static int decode_anim(AVCodecContext *avctx, int *got_frame_ptr)
2785 {
2786  SANMVideoContext *ctx = avctx->priv_data;
2787  int i, ret, to_store = 0, have_img = 0;
2788 
2789  ctx->first_fob = 1;
2790  while (bytestream2_get_bytes_left(&ctx->gb) >= 8) {
2791  uint32_t sig, size;
2792  int pos;
2793 
2794  sig = bytestream2_get_be32u(&ctx->gb);
2795  size = bytestream2_get_be32u(&ctx->gb);
2796  pos = bytestream2_tell(&ctx->gb);
2797 
2798  if (bytestream2_get_bytes_left(&ctx->gb) < size) {
2799  av_log(avctx, AV_LOG_ERROR, "Incorrect chunk size %"PRIu32".\n", size);
2800  break;
2801  }
2802  switch (sig) {
2803  case MKBETAG('N', 'P', 'A', 'L'):
2804  if (size != PALETTE_SIZE * 3) {
2805  av_log(avctx, AV_LOG_ERROR,
2806  "Incorrect palette block size %"PRIu32".\n", size);
2807  return AVERROR_INVALIDDATA;
2808  }
2809  for (i = 0; i < PALETTE_SIZE; i++)
2810  ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb);
2811  if (ctx->subversion < 2)
2812  ctx->pal[0] = 0xFFU << 24;
2813  break;
2814  case MKBETAG('F', 'O', 'B', 'J'):
2815  if (size < 16)
2816  return AVERROR_INVALIDDATA;
2818  bytestream2_init(&fc, ctx->gb.buffer, size);
2819  if (ret = process_frame_obj(ctx, &fc, 0, 0)) {
2820  return ret;
2821  }
2822  have_img = 1;
2823 
2824  /* STOR: for ANIMv0/1 store the whole FOBJ datablock, as it
2825  * needs to be replayed on FTCH, since none of the codecs
2826  * it uses work on the full buffer.
2827  * For ANIMv2, it's enough to store the current framebuffer.
2828  */
2829  if (to_store) {
2830  to_store = 0;
2831  if (ctx->subversion < 2) {
2832  if (size <= ctx->stored_frame_size) {
2833  bytestream2_seek(&fc, 0, SEEK_SET);
2834  bytestream2_get_bufferu(&fc, ctx->stored_frame, size);
2835  ctx->stor_size = size;
2836  } else {
2837  av_log(avctx, AV_LOG_ERROR, "FOBJ too large for STOR\n");
2838  ret = AVERROR(ENOMEM);
2839  }
2840  } else {
2841  memcpy(ctx->stored_frame, ctx->fbuf, ctx->buf_size);
2842  ctx->stor_size = ctx->buf_size;
2843  }
2844  }
2845  bytestream2_skip(&ctx->gb, size);
2846  break;
2847  case MKBETAG('X', 'P', 'A', 'L'):
2848  if (ret = process_xpal(ctx, size))
2849  return ret;
2850  break;
2851  case MKBETAG('S', 'T', 'O', 'R'):
2852  to_store = 1;
2853  break;
2854  case MKBETAG('F', 'T', 'C', 'H'):
2855  if (ctx->subversion < 2) {
2856  if ((ret = process_ftch(ctx, size)) < 0)
2857  return ret;
2858  have_img = (ret == 0) ? 1 : 0;
2859  } else {
2860  if (ctx->stor_size > 0) {
2861  memcpy(ctx->fbuf, ctx->stored_frame, ctx->buf_size);
2862  have_img = 1;
2863  }
2864  }
2865  break;
2866  default:
2867  bytestream2_skip(&ctx->gb, size);
2868  av_log(avctx, AV_LOG_DEBUG,
2869  "Unknown/unsupported chunk %"PRIx32".\n", sig);
2870  break;
2871  }
2872 
2873  /* the sizes of chunks are usually a multiple of 2. However
2874  * there are a few unaligned FOBJs in RA1 L2PLAY.ANM only (looks
2875  * like a game bug) and IACT audio chunks which have odd sizes
2876  * but are padded with a zero byte.
2877  */
2878  bytestream2_seek(&ctx->gb, pos + size, SEEK_SET);
2879  if ((pos + size) & 1) {
2880  if (bytestream2_peek_byte(&ctx->gb) == 0)
2881  bytestream2_skip(&ctx->gb, 1);
2882  }
2883  }
2884 
2885  if (have_img) {
2886  if ((ret = copy_output(ctx, 0)))
2887  return ret;
2888  memcpy(ctx->frame->data[1], ctx->pal, 1024);
2889  *got_frame_ptr = 1;
2890  }
2891  return 0;
2892 }
2893 
2895  int *got_frame_ptr, AVPacket *pkt)
2896 {
2897  SANMVideoContext *ctx = avctx->priv_data;
2898  int ret;
2899 
2900  ctx->frame = frame;
2901  bytestream2_init(&ctx->gb, pkt->data, pkt->size);
2902 
2903  if (!ctx->version) {
2904  if ((ret = decode_anim(avctx, got_frame_ptr)))
2905  return ret;
2906  } else {
2907  if ((ret = decode_bl16(avctx, got_frame_ptr)))
2908  return ret;
2909  }
2910  return pkt->size;
2911 }
2912 
2914  .p.name = "sanm",
2915  CODEC_LONG_NAME("LucasArts SANM/Smush video"),
2916  .p.type = AVMEDIA_TYPE_VIDEO,
2917  .p.id = AV_CODEC_ID_SANM,
2918  .priv_data_size = sizeof(SANMVideoContext),
2919  .init = decode_init,
2920  .close = decode_end,
2922  .p.capabilities = AV_CODEC_CAP_DR1,
2923 };
SANMVideoContext::width
int width
Definition: sanm.c:277
flags
const SwsFlags flags[]
Definition: swscale.c:72
rle_decode
static int rle_decode(SANMVideoContext *ctx, GetByteContext *gb, uint8_t *dst, const int out_size)
Definition: sanm.c:759
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
SANMVideoContext::fbuf_size
uint32_t fbuf_size
Definition: sanm.c:284
bl16_decode_6
static int bl16_decode_6(SANMVideoContext *ctx)
Definition: sanm.c:2582
codec47_comp1
static void codec47_comp1(GetByteContext *gb, uint8_t *dst_in, int width, const int height, const ptrdiff_t stride, const uint8_t *itbl)
Definition: sanm.c:1519
BOTTOM_EDGE
@ BOTTOM_EDGE
Definition: sanm.c:311
SANMVideoContext::rle_buf
uint8_t * rle_buf
Definition: sanm.c:288
old_codec37
static int old_codec37(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int width, int height)
Definition: sanm.c:1233
fill_block
static void fill_block(uint16_t *pdest, uint16_t color, int block_size, ptrdiff_t pitch)
Definition: sanm.c:2338
r
const char * r
Definition: vf_curves.c:127
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
bytestream2_get_bytes_left
static av_always_inline int bytestream2_get_bytes_left(const GetByteContext *g)
Definition: bytestream.h:158
make_glyphs
static void make_glyphs(int8_t *pglyphs, const int8_t *xvec, const int8_t *yvec, const int side_length)
Construct glyphs by iterating through vector coordinates.
Definition: sanm.c:389
blt_mask
static void blt_mask(uint8_t *dst, const uint8_t *src, int16_t left, int16_t top, uint16_t srcxoff, uint16_t srcyoff, uint16_t srcwidth, uint16_t srcheight, const uint16_t srcpitch, const uint16_t dstpitch, const uint16_t dstheight, int32_t size, const uint8_t skipcolor)
Definition: sanm.c:1099
color
Definition: vf_paletteuse.c:513
GetByteContext
Definition: bytestream.h:33
SANMVideoContext::pal
uint32_t pal[PALETTE_SIZE]
Definition: sanm.c:273
bytestream2_tell
static av_always_inline int bytestream2_tell(const GetByteContext *g)
Definition: bytestream.h:192
bl16_decode_5
static int bl16_decode_5(SANMVideoContext *ctx, int rle_size)
Definition: sanm.c:2559
src1
const pixel * src1
Definition: h264pred_template.c:420
SANMVideoContext::stored_frame
uint8_t * stored_frame
Definition: sanm.c:283
SANMVideoContext::aligned_height
int aligned_height
Definition: sanm.c:278
SANMVideoContext::p4x4glyphs
int8_t p4x4glyphs[NGLYPHS][16]
Definition: sanm.c:296
good_mvec
static int good_mvec(SANMVideoContext *ctx, int cx, int cy, int mx, int my, int block_size)
Definition: sanm.c:2432
mask
int mask
Definition: mediacodecdec_common.c:154
out_size
static int out_size
Definition: movenc.c:56
blt_solid
static void blt_solid(uint8_t *dst, const uint8_t *src, int16_t left, int16_t top, uint16_t srcxoff, uint16_t srcyoff, uint16_t srcwidth, uint16_t srcheight, const uint16_t srcpitch, const uint16_t dstpitch, const uint16_t dstheight, int32_t size)
Definition: sanm.c:1047
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:963
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:435
AVPacket::data
uint8_t * data
Definition: packet.h:595
b
#define b
Definition: input.c:43
decode_end
static av_cold int decode_end(AVCodecContext *avctx)
Definition: sanm.c:683
bl16_decode_1
static int bl16_decode_1(SANMVideoContext *ctx)
Definition: sanm.c:2275
bl16_decode_0
static int bl16_decode_0(SANMVideoContext *ctx)
Definition: sanm.c:2246
interp_point
static void interp_point(int8_t *points, int x0, int y0, int x1, int y1, int pos, int npoints)
Definition: sanm.c:369
FFCodec
Definition: codec_internal.h:127
copy_block8
static void copy_block8(uint8_t *dst, const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t srcStride, int h)
Definition: copy_block.h:47
bl16_block
static int bl16_block(SANMVideoContext *ctx, int cx, int cy, int blk_size)
Definition: sanm.c:2448
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
c1
static const uint64_t c1
Definition: murmur3.c:52
ff_set_dimensions
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Definition: utils.c:91
ff_sanm_decoder
const FFCodec ff_sanm_decoder
Definition: sanm.c:2913
bit
#define bit(string, value)
Definition: cbs_mpeg2.c:56
c48_invalid_mv
static int c48_invalid_mv(int x, int y, const uint16_t w, int h, int blocksize, int mvofs)
Definition: sanm.c:1663
px
#define px
Definition: ops_tmpl_float.c:35
close
static av_cold void close(AVCodecParserContext *s)
Definition: apv_parser.c:197
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:281
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
copy_output
static int copy_output(SANMVideoContext *ctx, int sanm)
Definition: sanm.c:2676
LEFT_EDGE
@ LEFT_EDGE
Definition: sanm.c:308
glyph8_x
static const int8_t glyph8_x[GLYPH_COORD_VECT_SIZE]
Definition: sanm.c:45
SANMVideoContext::gb
GetByteContext gb
Definition: sanm.c:270
destroy_buffers
static void destroy_buffers(SANMVideoContext *ctx)
Definition: sanm.c:454
val
static double val(void *priv, double ch)
Definition: aeval.c:77
loop
static int loop
Definition: ffplay.c:337
SANMVideoContext::small_codebook
uint16_t small_codebook[4]
Definition: sanm.c:294
DIR_LEFT
@ DIR_LEFT
Definition: sanm.c:316
which_edge
static enum GlyphEdge which_edge(int x, int y, int edge_size)
Return enum GlyphEdge of box where point (x, y) lies.
Definition: sanm.c:330
NO_EDGE
@ NO_EDGE
Definition: sanm.c:312
SANMVideoContext::stor_size
uint32_t stor_size
Definition: sanm.c:285
TOP_EDGE
@ TOP_EDGE
Definition: sanm.c:309
avassert.h
SANMVideoContext::have_dimensions
int have_dimensions
Definition: sanm.c:272
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
av_cold
#define av_cold
Definition: attributes.h:119
AV_FRAME_FLAG_KEY
#define AV_FRAME_FLAG_KEY
A flag to mark frames that are keyframes.
Definition: frame.h:650
bl16_decode_7
static int bl16_decode_7(SANMVideoContext *ctx)
Definition: sanm.c:2602
av_memcpy_backptr
void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
Overlapping memcpy() implementation.
Definition: mem.c:447
clip
clip
Definition: af_crystalizer.c:122
AVCodecContext::extradata_size
int extradata_size
Definition: avcodec.h:523
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:347
process_frame_obj
static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb, int xoff, int yoff)
Definition: sanm.c:2021
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1414
c48_4to8
static void c48_4to8(uint8_t *dst, const uint8_t *src, const uint16_t w)
Definition: sanm.c:1648
g
const char * g
Definition: vf_curves.c:128
old_codec47
static int old_codec47(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int width, int height)
Definition: sanm.c:1552
GetByteContext::buffer
const uint8_t * buffer
Definition: bytestream.h:34
fc
#define fc(width, name, range_min, range_max)
Definition: cbs_av1.c:494
SANMVideoContext::npixels
long npixels
Definition: sanm.c:291
bits
uint8_t bits
Definition: vp3data.h:128
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:42
old_codec2
static int old_codec2(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int width, int height)
Definition: sanm.c:1029
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:231
SANMVideoContext::c45tbl2
uint8_t c45tbl2[0x8000]
Definition: sanm.c:304
opcode_0xf8
static int opcode_0xf8(SANMVideoContext *ctx, int cx, int cy, int block_size, ptrdiff_t pitch)
Definition: sanm.c:2404
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
SANMVideoContext::stored_frame_size
uint32_t stored_frame_size
Definition: sanm.c:286
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
codec47_read_interptable
static void codec47_read_interptable(GetByteContext *gb, uint8_t *itbl)
Definition: sanm.c:1503
bl16_decode_2
static int bl16_decode_2(SANMVideoContext *ctx)
Definition: sanm.c:2547
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:332
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
GlyphEdge
GlyphEdge
Definition: sanm.c:307
init_sizes
static void init_sizes(SANMVideoContext *ctx, int width, int height)
Definition: sanm.c:441
copy_block16
static void copy_block16(uint8_t *dst, const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t srcStride, int h)
Definition: copy_block.h:68
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:278
old_codec23
static int old_codec23(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int width, int height, uint8_t param, uint16_t param2)
Definition: sanm.c:785
SANMVideoContext::avctx
AVCodecContext * avctx
Definition: sanm.c:269
SANMVideoContext::subversion
int subversion
Definition: sanm.c:272
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:2348
bl16_decode_8
static int bl16_decode_8(SANMVideoContext *ctx)
Definition: sanm.c:2646
AV_PICTURE_TYPE_I
@ AV_PICTURE_TYPE_I
Intra.
Definition: avutil.h:278
PALETTE_SIZE
#define PALETTE_SIZE
Definition: sanm.c:34
SANMVideoContext::frm1_size
uint32_t frm1_size
Definition: sanm.c:284
SANMVideoContext::frm1
uint16_t * frm1
Definition: sanm.c:282
rotate_bufs
static void rotate_bufs(SANMVideoContext *ctx, int rotate_code)
Definition: sanm.c:620
SANMVideoContext::c47itbl
uint8_t c47itbl[0x10000]
Definition: sanm.c:298
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:553
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:284
ff_get_buffer
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1765
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:551
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:596
SANMVideoContext
Definition: sanm.c:268
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:1214
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
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
size
int size
Definition: twinvq_data.h:10344
color
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:98
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:272
bl16_c1_avg_col
static uint16_t bl16_c1_avg_col(uint16_t c1, uint16_t c2)
Definition: sanm.c:2264
SANMVideoContext::frm0
uint16_t * frm0
Definition: sanm.c:282
c47_mv
static const int8_t c47_mv[256][2]
Definition: sanm.c:54
SANMVideoContext::c4param
uint16_t c4param
Definition: sanm.c:301
SANMVideoContext::c23lut
uint8_t c23lut[256]
Definition: sanm.c:299
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:692
decode_init
static av_cold int decode_init(AVCodecContext *avctx)
Definition: sanm.c:627
xf
#define xf(width, name, var, range_min, range_max, subs,...)
Definition: cbs_av1.c:622
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
old_codec20
static int old_codec20(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, const int w, const int h)
Definition: sanm.c:1205
av_malloc
#define av_malloc(s)
Definition: ops_asmgen.c:44
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:646
fill_frame
static void fill_frame(uint16_t *pbuf, int buf_size, uint16_t color)
Definition: sanm.c:2668
copy_block.h
copy_block
static void copy_block(uint16_t *pdest, uint16_t *psrc, int block_size, ptrdiff_t pitch)
Definition: sanm.c:2319
AVCodecContext::extradata
uint8_t * extradata
Out-of-band global headers that may be used by some codecs.
Definition: avcodec.h:522
src2
const pixel * src2
Definition: h264pred_template.c:421
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
process_xpal
static int process_xpal(SANMVideoContext *ctx, int size)
Definition: sanm.c:2199
SANMVideoContext::shift_pal
int16_t shift_pal[PALETTE_DELTA]
Definition: sanm.c:274
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:179
SANMVideoContext::fbuf
uint16_t * fbuf
Definition: sanm.c:282
SANMVideoContext::first_fob
int first_fob
Definition: sanm.c:272
len
int len
Definition: vorbis_enc_data.h:426
AVCodecContext::height
int height
Definition: avcodec.h:600
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:639
decode_anim
static int decode_anim(AVCodecContext *avctx, int *got_frame_ptr)
Definition: sanm.c:2784
AV_PIX_FMT_RGB565
#define AV_PIX_FMT_RGB565
Definition: pixfmt.h:526
avcodec.h
SANMVideoContext::codebook
uint16_t codebook[256]
Definition: sanm.c:293
GlyphDir
GlyphDir
Definition: sanm.c:315
AV_PIX_FMT_PAL8
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:84
DIR_DOWN
@ DIR_DOWN
Definition: sanm.c:319
ret
ret
Definition: filter_design.txt:187
glyph4_x
static const int8_t glyph4_x[GLYPH_COORD_VECT_SIZE]
Definition: sanm.c:37
FFSWAP
#define FFSWAP(type, a, b)
Definition: macros.h:52
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:265
SANMVideoContext::frm2
uint16_t * frm2
Definition: sanm.c:282
DIR_RIGHT
@ DIR_RIGHT
Definition: sanm.c:318
pos
unsigned int pos
Definition: spdifenc.c:414
decode_bl16
static int decode_bl16(AVCodecContext *avctx, int *got_frame_ptr)
Definition: sanm.c:2698
c37_mv
static const int8_t c37_mv[]
Definition: sanm.c:109
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:851
codec47_block
static int codec47_block(SANMVideoContext *ctx, GetByteContext *gb, uint8_t *dst, uint8_t *prev1, uint8_t *prev2, int stride, int size)
Definition: sanm.c:1417
AVCodecContext
main external API structure.
Definition: avcodec.h:439
c2
static const uint64_t c2
Definition: murmur3.c:53
SANMVideoContext::c47cb
uint8_t c47cb[4]
Definition: sanm.c:302
SANMVideoContext::rle_buf_size
unsigned int rle_buf_size
Definition: sanm.c:289
SANMVideoContext::buf_size
long buf_size
Definition: sanm.c:291
codec48_block
static int codec48_block(GetByteContext *gb, uint8_t *dst, uint8_t *db, int x, int y, const uint16_t w, const int aligned_height, const uint8_t *itbl)
Definition: sanm.c:1673
blt_ipol
static void blt_ipol(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int16_t left, int16_t top, uint16_t srcxoff, uint16_t srcyoff, uint16_t srcwidth, uint16_t srcheight, const uint16_t srcpitch, const uint16_t dstpitch, const uint16_t dstheight, int32_t size, const uint8_t *itbl)
Definition: sanm.c:1151
av_fast_padded_mallocz
void av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size)
Same behaviour av_fast_padded_malloc except that buffer will always be 0-initialized after call.
Definition: utils.c:66
which_direction
static enum GlyphDir which_direction(enum GlyphEdge edge0, enum GlyphEdge edge1)
Definition: sanm.c:346
SANMVideoContext::c4tbl
uint8_t c4tbl[2][256][16]
Definition: sanm.c:300
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:602
av_clip_uint8
#define av_clip_uint8
Definition: common.h:106
SANMVideoContext::c45tbl1
uint8_t c45tbl1[0x300]
Definition: sanm.c:303
RIGHT_EDGE
@ RIGHT_EDGE
Definition: sanm.c:310
AV_PICTURE_TYPE_P
@ AV_PICTURE_TYPE_P
Predicted.
Definition: avutil.h:279
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:200
SANMVideoContext::p8x8glyphs
int8_t p8x8glyphs[NGLYPHS][64]
Definition: sanm.c:297
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:2370
w
uint8_t w
Definition: llvidencdsp.c:39
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:572
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:466
codec33_gen_tiles
static void codec33_gen_tiles(SANMVideoContext *ctx, int8_t param1)
Definition: sanm.c:489
old_codec48
static int old_codec48(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int width, int height)
Definition: sanm.c:1850
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
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:600
int32_t
int32_t
Definition: audioconvert.c:56
bytestream.h
old_codec45
static void old_codec45(SANMVideoContext *ctx, GetByteContext *gb, int top, int left, int flag)
Definition: sanm.c:1961
bytestream2_init
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
DIR_UP
@ DIR_UP
Definition: sanm.c:317
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:2159
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:896
SANMVideoContext::delta_pal
int16_t delta_pal[PALETTE_DELTA]
Definition: sanm.c:274
stride
#define stride
Definition: h264pred_template.c:536
NO_DIR
@ NO_DIR
Definition: sanm.c:320
pkt
static AVPacket * pkt
Definition: demux_decode.c:55
width
#define width
Definition: dsp.h:89
av_bswap16
#define av_bswap16
Definition: bswap.h:28
SANMVideoContext::pitch
ptrdiff_t pitch
Definition: sanm.c:276
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:284
SANMVideoContext::prev_seq
int prev_seq
Definition: sanm.c:279
SANMVideoContext::height
int height
Definition: sanm.c:277
decode_frame
static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *pkt)
Definition: sanm.c:2894
init_buffers
static av_cold int init_buffers(SANMVideoContext *ctx)
Definition: sanm.c:468