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