FFmpeg
sanm.c
Go to the documentation of this file.
1 /*
2  * LucasArts Smush video decoder
3  * Copyright (c) 2006 Cyril Zorin
4  * Copyright (c) 2011 Konstantin Shishkov
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include "libavutil/avassert.h"
24 #include "libavutil/mem.h"
25 
26 #include "avcodec.h"
27 #include "bytestream.h"
28 #include "copy_block.h"
29 #include "codec_internal.h"
30 #include "decode.h"
31 
32 #define NGLYPHS 256
33 #define GLYPH_COORD_VECT_SIZE 16
34 #define PALETTE_SIZE 256
35 #define PALETTE_DELTA 768
36 
37 static const int8_t glyph4_x[GLYPH_COORD_VECT_SIZE] = {
38  0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0, 1, 2, 2, 1
39 };
40 
41 static const int8_t glyph4_y[GLYPH_COORD_VECT_SIZE] = {
42  0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 2, 1, 1, 1, 2, 2
43 };
44 
45 static const int8_t glyph8_x[GLYPH_COORD_VECT_SIZE] = {
46  0, 2, 5, 7, 7, 7, 7, 7, 7, 5, 2, 0, 0, 0, 0, 0
47 };
48 
49 static const int8_t glyph8_y[GLYPH_COORD_VECT_SIZE] = {
50  0, 0, 0, 0, 1, 3, 4, 6, 7, 7, 7, 7, 6, 4, 3, 1
51 };
52 
53 static const int8_t motion_vectors[256][2] = {
54  { 0, 0 }, { -1, -43 }, { 6, -43 }, { -9, -42 }, { 13, -41 },
55  { -16, -40 }, { 19, -39 }, { -23, -36 }, { 26, -34 }, { -2, -33 },
56  { 4, -33 }, { -29, -32 }, { -9, -32 }, { 11, -31 }, { -16, -29 },
57  { 32, -29 }, { 18, -28 }, { -34, -26 }, { -22, -25 }, { -1, -25 },
58  { 3, -25 }, { -7, -24 }, { 8, -24 }, { 24, -23 }, { 36, -23 },
59  { -12, -22 }, { 13, -21 }, { -38, -20 }, { 0, -20 }, { -27, -19 },
60  { -4, -19 }, { 4, -19 }, { -17, -18 }, { -8, -17 }, { 8, -17 },
61  { 18, -17 }, { 28, -17 }, { 39, -17 }, { -12, -15 }, { 12, -15 },
62  { -21, -14 }, { -1, -14 }, { 1, -14 }, { -41, -13 }, { -5, -13 },
63  { 5, -13 }, { 21, -13 }, { -31, -12 }, { -15, -11 }, { -8, -11 },
64  { 8, -11 }, { 15, -11 }, { -2, -10 }, { 1, -10 }, { 31, -10 },
65  { -23, -9 }, { -11, -9 }, { -5, -9 }, { 4, -9 }, { 11, -9 },
66  { 42, -9 }, { 6, -8 }, { 24, -8 }, { -18, -7 }, { -7, -7 },
67  { -3, -7 }, { -1, -7 }, { 2, -7 }, { 18, -7 }, { -43, -6 },
68  { -13, -6 }, { -4, -6 }, { 4, -6 }, { 8, -6 }, { -33, -5 },
69  { -9, -5 }, { -2, -5 }, { 0, -5 }, { 2, -5 }, { 5, -5 },
70  { 13, -5 }, { -25, -4 }, { -6, -4 }, { -3, -4 }, { 3, -4 },
71  { 9, -4 }, { -19, -3 }, { -7, -3 }, { -4, -3 }, { -2, -3 },
72  { -1, -3 }, { 0, -3 }, { 1, -3 }, { 2, -3 }, { 4, -3 },
73  { 6, -3 }, { 33, -3 }, { -14, -2 }, { -10, -2 }, { -5, -2 },
74  { -3, -2 }, { -2, -2 }, { -1, -2 }, { 0, -2 }, { 1, -2 },
75  { 2, -2 }, { 3, -2 }, { 5, -2 }, { 7, -2 }, { 14, -2 },
76  { 19, -2 }, { 25, -2 }, { 43, -2 }, { -7, -1 }, { -3, -1 },
77  { -2, -1 }, { -1, -1 }, { 0, -1 }, { 1, -1 }, { 2, -1 },
78  { 3, -1 }, { 10, -1 }, { -5, 0 }, { -3, 0 }, { -2, 0 },
79  { -1, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 }, { 5, 0 },
80  { 7, 0 }, { -10, 1 }, { -7, 1 }, { -3, 1 }, { -2, 1 },
81  { -1, 1 }, { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 },
82  { -43, 2 }, { -25, 2 }, { -19, 2 }, { -14, 2 }, { -5, 2 },
83  { -3, 2 }, { -2, 2 }, { -1, 2 }, { 0, 2 }, { 1, 2 },
84  { 2, 2 }, { 3, 2 }, { 5, 2 }, { 7, 2 }, { 10, 2 },
85  { 14, 2 }, { -33, 3 }, { -6, 3 }, { -4, 3 }, { -2, 3 },
86  { -1, 3 }, { 0, 3 }, { 1, 3 }, { 2, 3 }, { 4, 3 },
87  { 19, 3 }, { -9, 4 }, { -3, 4 }, { 3, 4 }, { 7, 4 },
88  { 25, 4 }, { -13, 5 }, { -5, 5 }, { -2, 5 }, { 0, 5 },
89  { 2, 5 }, { 5, 5 }, { 9, 5 }, { 33, 5 }, { -8, 6 },
90  { -4, 6 }, { 4, 6 }, { 13, 6 }, { 43, 6 }, { -18, 7 },
91  { -2, 7 }, { 0, 7 }, { 2, 7 }, { 7, 7 }, { 18, 7 },
92  { -24, 8 }, { -6, 8 }, { -42, 9 }, { -11, 9 }, { -4, 9 },
93  { 5, 9 }, { 11, 9 }, { 23, 9 }, { -31, 10 }, { -1, 10 },
94  { 2, 10 }, { -15, 11 }, { -8, 11 }, { 8, 11 }, { 15, 11 },
95  { 31, 12 }, { -21, 13 }, { -5, 13 }, { 5, 13 }, { 41, 13 },
96  { -1, 14 }, { 1, 14 }, { 21, 14 }, { -12, 15 }, { 12, 15 },
97  { -39, 17 }, { -28, 17 }, { -18, 17 }, { -8, 17 }, { 8, 17 },
98  { 17, 18 }, { -4, 19 }, { 0, 19 }, { 4, 19 }, { 27, 19 },
99  { 38, 20 }, { -13, 21 }, { 12, 22 }, { -36, 23 }, { -24, 23 },
100  { -8, 24 }, { 7, 24 }, { -3, 25 }, { 1, 25 }, { 22, 25 },
101  { 34, 26 }, { -18, 28 }, { -32, 29 }, { 16, 29 }, { -11, 31 },
102  { 9, 32 }, { 29, 32 }, { -4, 33 }, { 2, 33 }, { -26, 34 },
103  { 23, 36 }, { -19, 39 }, { 16, 40 }, { -13, 41 }, { 9, 42 },
104  { -6, 43 }, { 1, 43 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
105 };
106 
107 static const int8_t c37_mv[] = {
108  0, 0, 1, 0, 2, 0, 3, 0, 5, 0,
109  8, 0, 13, 0, 21, 0, -1, 0, -2, 0,
110  -3, 0, -5, 0, -8, 0, -13, 0, -17, 0,
111  -21, 0, 0, 1, 1, 1, 2, 1, 3, 1,
112  5, 1, 8, 1, 13, 1, 21, 1, -1, 1,
113  -2, 1, -3, 1, -5, 1, -8, 1, -13, 1,
114  -17, 1, -21, 1, 0, 2, 1, 2, 2, 2,
115  3, 2, 5, 2, 8, 2, 13, 2, 21, 2,
116  -1, 2, -2, 2, -3, 2, -5, 2, -8, 2,
117  -13, 2, -17, 2, -21, 2, 0, 3, 1, 3,
118  2, 3, 3, 3, 5, 3, 8, 3, 13, 3,
119  21, 3, -1, 3, -2, 3, -3, 3, -5, 3,
120  -8, 3, -13, 3, -17, 3, -21, 3, 0, 5,
121  1, 5, 2, 5, 3, 5, 5, 5, 8, 5,
122  13, 5, 21, 5, -1, 5, -2, 5, -3, 5,
123  -5, 5, -8, 5, -13, 5, -17, 5, -21, 5,
124  0, 8, 1, 8, 2, 8, 3, 8, 5, 8,
125  8, 8, 13, 8, 21, 8, -1, 8, -2, 8,
126  -3, 8, -5, 8, -8, 8, -13, 8, -17, 8,
127  -21, 8, 0, 13, 1, 13, 2, 13, 3, 13,
128  5, 13, 8, 13, 13, 13, 21, 13, -1, 13,
129  -2, 13, -3, 13, -5, 13, -8, 13, -13, 13,
130  -17, 13, -21, 13, 0, 21, 1, 21, 2, 21,
131  3, 21, 5, 21, 8, 21, 13, 21, 21, 21,
132  -1, 21, -2, 21, -3, 21, -5, 21, -8, 21,
133  -13, 21, -17, 21, -21, 21, 0, -1, 1, -1,
134  2, -1, 3, -1, 5, -1, 8, -1, 13, -1,
135  21, -1, -1, -1, -2, -1, -3, -1, -5, -1,
136  -8, -1, -13, -1, -17, -1, -21, -1, 0, -2,
137  1, -2, 2, -2, 3, -2, 5, -2, 8, -2,
138  13, -2, 21, -2, -1, -2, -2, -2, -3, -2,
139  -5, -2, -8, -2, -13, -2, -17, -2, -21, -2,
140  0, -3, 1, -3, 2, -3, 3, -3, 5, -3,
141  8, -3, 13, -3, 21, -3, -1, -3, -2, -3,
142  -3, -3, -5, -3, -8, -3, -13, -3, -17, -3,
143  -21, -3, 0, -5, 1, -5, 2, -5, 3, -5,
144  5, -5, 8, -5, 13, -5, 21, -5, -1, -5,
145  -2, -5, -3, -5, -5, -5, -8, -5, -13, -5,
146  -17, -5, -21, -5, 0, -8, 1, -8, 2, -8,
147  3, -8, 5, -8, 8, -8, 13, -8, 21, -8,
148  -1, -8, -2, -8, -3, -8, -5, -8, -8, -8,
149  -13, -8, -17, -8, -21, -8, 0, -13, 1, -13,
150  2, -13, 3, -13, 5, -13, 8, -13, 13, -13,
151  21, -13, -1, -13, -2, -13, -3, -13, -5, -13,
152  -8, -13, -13, -13, -17, -13, -21, -13, 0, -17,
153  1, -17, 2, -17, 3, -17, 5, -17, 8, -17,
154  13, -17, 21, -17, -1, -17, -2, -17, -3, -17,
155  -5, -17, -8, -17, -13, -17, -17, -17, -21, -17,
156  0, -21, 1, -21, 2, -21, 3, -21, 5, -21,
157  8, -21, 13, -21, 21, -21, -1, -21, -2, -21,
158  -3, -21, -5, -21, -8, -21, -13, -21, -17, -21,
159  0, 0, -8, -29, 8, -29, -18, -25, 17, -25,
160  0, -23, -6, -22, 6, -22, -13, -19, 12, -19,
161  0, -18, 25, -18, -25, -17, -5, -17, 5, -17,
162  -10, -15, 10, -15, 0, -14, -4, -13, 4, -13,
163  19, -13, -19, -12, -8, -11, -2, -11, 0, -11,
164  2, -11, 8, -11, -15, -10, -4, -10, 4, -10,
165  15, -10, -6, -9, -1, -9, 1, -9, 6, -9,
166  -29, -8, -11, -8, -8, -8, -3, -8, 3, -8,
167  8, -8, 11, -8, 29, -8, -5, -7, -2, -7,
168  0, -7, 2, -7, 5, -7, -22, -6, -9, -6,
169  -6, -6, -3, -6, -1, -6, 1, -6, 3, -6,
170  6, -6, 9, -6, 22, -6, -17, -5, -7, -5,
171  -4, -5, -2, -5, 0, -5, 2, -5, 4, -5,
172  7, -5, 17, -5, -13, -4, -10, -4, -5, -4,
173  -3, -4, -1, -4, 0, -4, 1, -4, 3, -4,
174  5, -4, 10, -4, 13, -4, -8, -3, -6, -3,
175  -4, -3, -3, -3, -2, -3, -1, -3, 0, -3,
176  1, -3, 2, -3, 4, -3, 6, -3, 8, -3,
177  -11, -2, -7, -2, -5, -2, -3, -2, -2, -2,
178  -1, -2, 0, -2, 1, -2, 2, -2, 3, -2,
179  5, -2, 7, -2, 11, -2, -9, -1, -6, -1,
180  -4, -1, -3, -1, -2, -1, -1, -1, 0, -1,
181  1, -1, 2, -1, 3, -1, 4, -1, 6, -1,
182  9, -1, -31, 0, -23, 0, -18, 0, -14, 0,
183  -11, 0, -7, 0, -5, 0, -4, 0, -3, 0,
184  -2, 0, -1, 0, 0, -31, 1, 0, 2, 0,
185  3, 0, 4, 0, 5, 0, 7, 0, 11, 0,
186  14, 0, 18, 0, 23, 0, 31, 0, -9, 1,
187  -6, 1, -4, 1, -3, 1, -2, 1, -1, 1,
188  0, 1, 1, 1, 2, 1, 3, 1, 4, 1,
189  6, 1, 9, 1, -11, 2, -7, 2, -5, 2,
190  -3, 2, -2, 2, -1, 2, 0, 2, 1, 2,
191  2, 2, 3, 2, 5, 2, 7, 2, 11, 2,
192  -8, 3, -6, 3, -4, 3, -2, 3, -1, 3,
193  0, 3, 1, 3, 2, 3, 3, 3, 4, 3,
194  6, 3, 8, 3, -13, 4, -10, 4, -5, 4,
195  -3, 4, -1, 4, 0, 4, 1, 4, 3, 4,
196  5, 4, 10, 4, 13, 4, -17, 5, -7, 5,
197  -4, 5, -2, 5, 0, 5, 2, 5, 4, 5,
198  7, 5, 17, 5, -22, 6, -9, 6, -6, 6,
199  -3, 6, -1, 6, 1, 6, 3, 6, 6, 6,
200  9, 6, 22, 6, -5, 7, -2, 7, 0, 7,
201  2, 7, 5, 7, -29, 8, -11, 8, -8, 8,
202  -3, 8, 3, 8, 8, 8, 11, 8, 29, 8,
203  -6, 9, -1, 9, 1, 9, 6, 9, -15, 10,
204  -4, 10, 4, 10, 15, 10, -8, 11, -2, 11,
205  0, 11, 2, 11, 8, 11, 19, 12, -19, 13,
206  -4, 13, 4, 13, 0, 14, -10, 15, 10, 15,
207  -5, 17, 5, 17, 25, 17, -25, 18, 0, 18,
208  -12, 19, 13, 19, -6, 22, 6, 22, 0, 23,
209  -17, 25, 18, 25, -8, 29, 8, 29, 0, 31,
210  0, 0, -6, -22, 6, -22, -13, -19, 12, -19,
211  0, -18, -5, -17, 5, -17, -10, -15, 10, -15,
212  0, -14, -4, -13, 4, -13, 19, -13, -19, -12,
213  -8, -11, -2, -11, 0, -11, 2, -11, 8, -11,
214  -15, -10, -4, -10, 4, -10, 15, -10, -6, -9,
215  -1, -9, 1, -9, 6, -9, -11, -8, -8, -8,
216  -3, -8, 0, -8, 3, -8, 8, -8, 11, -8,
217  -5, -7, -2, -7, 0, -7, 2, -7, 5, -7,
218  -22, -6, -9, -6, -6, -6, -3, -6, -1, -6,
219  1, -6, 3, -6, 6, -6, 9, -6, 22, -6,
220  -17, -5, -7, -5, -4, -5, -2, -5, -1, -5,
221  0, -5, 1, -5, 2, -5, 4, -5, 7, -5,
222  17, -5, -13, -4, -10, -4, -5, -4, -3, -4,
223  -2, -4, -1, -4, 0, -4, 1, -4, 2, -4,
224  3, -4, 5, -4, 10, -4, 13, -4, -8, -3,
225  -6, -3, -4, -3, -3, -3, -2, -3, -1, -3,
226  0, -3, 1, -3, 2, -3, 3, -3, 4, -3,
227  6, -3, 8, -3, -11, -2, -7, -2, -5, -2,
228  -4, -2, -3, -2, -2, -2, -1, -2, 0, -2,
229  1, -2, 2, -2, 3, -2, 4, -2, 5, -2,
230  7, -2, 11, -2, -9, -1, -6, -1, -5, -1,
231  -4, -1, -3, -1, -2, -1, -1, -1, 0, -1,
232  1, -1, 2, -1, 3, -1, 4, -1, 5, -1,
233  6, -1, 9, -1, -23, 0, -18, 0, -14, 0,
234  -11, 0, -7, 0, -5, 0, -4, 0, -3, 0,
235  -2, 0, -1, 0, 0, -23, 1, 0, 2, 0,
236  3, 0, 4, 0, 5, 0, 7, 0, 11, 0,
237  14, 0, 18, 0, 23, 0, -9, 1, -6, 1,
238  -5, 1, -4, 1, -3, 1, -2, 1, -1, 1,
239  0, 1, 1, 1, 2, 1, 3, 1, 4, 1,
240  5, 1, 6, 1, 9, 1, -11, 2, -7, 2,
241  -5, 2, -4, 2, -3, 2, -2, 2, -1, 2,
242  0, 2, 1, 2, 2, 2, 3, 2, 4, 2,
243  5, 2, 7, 2, 11, 2, -8, 3, -6, 3,
244  -4, 3, -3, 3, -2, 3, -1, 3, 0, 3,
245  1, 3, 2, 3, 3, 3, 4, 3, 6, 3,
246  8, 3, -13, 4, -10, 4, -5, 4, -3, 4,
247  -2, 4, -1, 4, 0, 4, 1, 4, 2, 4,
248  3, 4, 5, 4, 10, 4, 13, 4, -17, 5,
249  -7, 5, -4, 5, -2, 5, -1, 5, 0, 5,
250  1, 5, 2, 5, 4, 5, 7, 5, 17, 5,
251  -22, 6, -9, 6, -6, 6, -3, 6, -1, 6,
252  1, 6, 3, 6, 6, 6, 9, 6, 22, 6,
253  -5, 7, -2, 7, 0, 7, 2, 7, 5, 7,
254  -11, 8, -8, 8, -3, 8, 0, 8, 3, 8,
255  8, 8, 11, 8, -6, 9, -1, 9, 1, 9,
256  6, 9, -15, 10, -4, 10, 4, 10, 15, 10,
257  -8, 11, -2, 11, 0, 11, 2, 11, 8, 11,
258  19, 12, -19, 13, -4, 13, 4, 13, 0, 14,
259  -10, 15, 10, 15, -5, 17, 5, 17, 0, 18,
260  -12, 19, 13, 19, -6, 22, 6, 22, 0, 23,
261 };
262 
263 typedef struct SANMVideoContext {
266 
268  uint32_t pal[PALETTE_SIZE];
270 
271  ptrdiff_t pitch;
272  int width, height;
274  int prev_seq;
275 
277  uint16_t *frm0, *frm1, *frm2;
278  uint8_t *stored_frame;
281 
282  uint8_t *rle_buf;
283  unsigned int rle_buf_size;
284 
286 
288 
289  uint16_t codebook[256];
290  uint16_t small_codebook[4];
291 
292  int8_t p4x4glyphs[NGLYPHS][16];
293  int8_t p8x8glyphs[NGLYPHS][64];
294  uint8_t c47itbl[0x10000];
296 
297 typedef struct SANMFrameHeader {
299 
300  uint16_t bg_color;
301  uint32_t width, height;
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->frm0);
454  av_freep(&ctx->frm1);
455  av_freep(&ctx->frm2);
456  av_freep(&ctx->stored_frame);
457  av_freep(&ctx->rle_buf);
458  ctx->frm0_size =
459  ctx->frm1_size =
460  ctx->frm2_size = 0;
461  init_sizes(ctx, 0, 0);
462 }
463 
465 {
466  av_fast_padded_mallocz(&ctx->frm0, &ctx->frm0_size, ctx->buf_size);
467  av_fast_padded_mallocz(&ctx->frm1, &ctx->frm1_size, ctx->buf_size);
468  av_fast_padded_mallocz(&ctx->frm2, &ctx->frm2_size, ctx->buf_size);
469  if (!ctx->version)
470  av_fast_padded_mallocz(&ctx->stored_frame,
471  &ctx->stored_frame_size, ctx->buf_size);
472 
473  if (!ctx->frm0 || !ctx->frm1 || !ctx->frm2 ||
474  (!ctx->stored_frame && !ctx->version)) {
476  return AVERROR(ENOMEM);
477  }
478 
479  return 0;
480 }
481 
482 static void rotate_bufs(SANMVideoContext *ctx, int rotate_code)
483 {
484  if (rotate_code == 2)
485  FFSWAP(uint16_t*, ctx->frm1, ctx->frm2);
486  FFSWAP(uint16_t*, ctx->frm2, ctx->frm0);
487 }
488 
490 {
491  SANMVideoContext *ctx = avctx->priv_data;
492 
493  ctx->avctx = avctx;
494  ctx->version = !avctx->extradata_size;
495  // early sanity check before allocations to avoid need for deallocation code.
496  if (!ctx->version && avctx->extradata_size < 1026) {
497  av_log(avctx, AV_LOG_ERROR, "Not enough extradata.\n");
498  return AVERROR_INVALIDDATA;
499  }
500 
501  avctx->pix_fmt = ctx->version ? AV_PIX_FMT_RGB565 : AV_PIX_FMT_PAL8;
502 
503  init_sizes(ctx, avctx->width, avctx->height);
504  if (init_buffers(ctx)) {
505  av_log(avctx, AV_LOG_ERROR, "Error allocating buffers.\n");
506  return AVERROR(ENOMEM);
507  }
508 
509  make_glyphs(ctx->p4x4glyphs[0], glyph4_x, glyph4_y, 4);
510  make_glyphs(ctx->p8x8glyphs[0], glyph8_x, glyph8_y, 8);
511 
512  if (!ctx->version) {
513  int i;
514 
515  ctx->subversion = AV_RL16(avctx->extradata);
516  for (i = 0; i < PALETTE_SIZE; i++)
517  ctx->pal[i] = 0xFFU << 24 | AV_RL32(avctx->extradata + 2 + i * 4);
518  }
519 
520  return 0;
521 }
522 
524 {
525  SANMVideoContext *ctx = avctx->priv_data;
526 
528 
529  return 0;
530 }
531 
532 static int rle_decode(SANMVideoContext *ctx, uint8_t *dst, const int out_size)
533 {
534  int opcode, color, run_len, left = out_size;
535 
536  while (left > 0) {
537  opcode = bytestream2_get_byte(&ctx->gb);
538  run_len = (opcode >> 1) + 1;
539  if (run_len > left || bytestream2_get_bytes_left(&ctx->gb) <= 0)
540  return AVERROR_INVALIDDATA;
541 
542  if (opcode & 1) {
543  color = bytestream2_get_byte(&ctx->gb);
544  memset(dst, color, run_len);
545  } else {
547  return AVERROR_INVALIDDATA;
549  }
550 
551  dst += run_len;
552  left -= run_len;
553  }
554 
555  return 0;
556 }
557 
558 static int old_codec1(SANMVideoContext *ctx, int top,
559  int left, int width, int height)
560 {
561  uint8_t *dst = ((uint8_t *)ctx->frm0) + left + top * ctx->pitch;
562  int i, j, len, flag, code, val, pos, end;
563 
564  for (i = 0; i < height; i++) {
565  pos = 0;
566 
567  if (bytestream2_get_bytes_left(&ctx->gb) < 2)
568  return AVERROR_INVALIDDATA;
569 
570  len = bytestream2_get_le16u(&ctx->gb);
571  end = bytestream2_tell(&ctx->gb) + len;
572 
573  while (bytestream2_tell(&ctx->gb) < end) {
574  if (bytestream2_get_bytes_left(&ctx->gb) < 2)
575  return AVERROR_INVALIDDATA;
576 
577  code = bytestream2_get_byteu(&ctx->gb);
578  flag = code & 1;
579  code = (code >> 1) + 1;
580  if (pos + code > width)
581  return AVERROR_INVALIDDATA;
582  if (flag) {
583  val = bytestream2_get_byteu(&ctx->gb);
584  if (val)
585  memset(dst + pos, val, code);
586  pos += code;
587  } else {
588  if (bytestream2_get_bytes_left(&ctx->gb) < code)
589  return AVERROR_INVALIDDATA;
590  for (j = 0; j < code; j++) {
591  val = bytestream2_get_byteu(&ctx->gb);
592  if (val)
593  dst[pos] = val;
594  pos++;
595  }
596  }
597  }
598  dst += ctx->pitch;
599  }
600  ctx->rotate_code = 0;
601 
602  return 0;
603 }
604 
605 static inline void codec37_mv(uint8_t *dst, const uint8_t *src,
606  int height, int stride, int x, int y)
607 {
608  int pos, i, j;
609 
610  pos = x + y * stride;
611  for (j = 0; j < 4; j++) {
612  for (i = 0; i < 4; i++) {
613  if ((pos + i) < 0 || (pos + i) >= height * stride)
614  dst[i] = 0;
615  else
616  dst[i] = src[i];
617  }
618  dst += stride;
619  src += stride;
620  pos += stride;
621  }
622 }
623 
624 static int old_codec37(SANMVideoContext *ctx, int top,
625  int left, int width, int height)
626 {
627  int i, j, k, l, t, run, len, code, skip, mx, my;
628  ptrdiff_t stride = ctx->pitch;
629  uint8_t *dst, *prev;
630  int skip_run = 0;
631  int compr = bytestream2_get_byte(&ctx->gb);
632  int mvoff = bytestream2_get_byte(&ctx->gb);
633  int seq = bytestream2_get_le16(&ctx->gb);
634  uint32_t decoded_size = bytestream2_get_le32(&ctx->gb);
635  int flags;
636 
637  bytestream2_skip(&ctx->gb, 4);
638  flags = bytestream2_get_byte(&ctx->gb);
639  bytestream2_skip(&ctx->gb, 3);
640 
641  if (decoded_size > ctx->height * stride - left - top * stride) {
642  decoded_size = ctx->height * stride - left - top * stride;
643  av_log(ctx->avctx, AV_LOG_WARNING, "Decoded size is too large.\n");
644  }
645 
646  ctx->rotate_code = 0;
647 
648  if (((seq & 1) || !(flags & 1)) && (compr && compr != 2))
649  rotate_bufs(ctx, 1);
650 
651  dst = ((uint8_t*)ctx->frm0) + left + top * stride;
652  prev = ((uint8_t*)ctx->frm2) + left + top * stride;
653 
654  if (mvoff > 2) {
655  av_log(ctx->avctx, AV_LOG_ERROR, "Invalid motion base value %d.\n", mvoff);
656  return AVERROR_INVALIDDATA;
657  }
658 
659  switch (compr) {
660  case 0:
661  for (i = 0; i < height; i++) {
663  dst += stride;
664  }
665  memset(ctx->frm1, 0, ctx->height * stride);
666  memset(ctx->frm2, 0, ctx->height * stride);
667  break;
668  case 1:
669  run = 0;
670  len = -1;
671  code = 0;
672 
673  for (j = 0; j < height; j += 4) {
674  for (i = 0; i < width; i += 4) {
675  if (len < 0) {
676  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
677  return AVERROR_INVALIDDATA;
678  code = bytestream2_get_byte(&ctx->gb);
679  len = code >> 1;
680  run = code & 1;
681  skip = 0;
682  } else {
683  skip = run;
684  }
685 
686  if (!skip) {
687  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
688  return AVERROR_INVALIDDATA;
689  code = bytestream2_get_byte(&ctx->gb);
690  if (code == 0xff) {
691  len--;
692  for (k = 0; k < 4; k++) {
693  for (l = 0; l < 4; l++) {
694  if (len < 0) {
695  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
696  return AVERROR_INVALIDDATA;
697  code = bytestream2_get_byte(&ctx->gb);
698  len = code >> 1;
699  run = code & 1;
700  if (run) {
701  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
702  return AVERROR_INVALIDDATA;
703  code = bytestream2_get_byte(&ctx->gb);
704  }
705  }
706  if (!run) {
707  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
708  return AVERROR_INVALIDDATA;
709  code = bytestream2_get_byte(&ctx->gb);
710  }
711  *(dst + i + (k * stride) + l) = code;
712  len--;
713  }
714  }
715  continue;
716  }
717  }
718  /* 4x4 block copy from prev with MV */
719  mx = c37_mv[(mvoff * 255 + code) * 2];
720  my = c37_mv[(mvoff * 255 + code) * 2 + 1];
721  codec37_mv(dst + i, prev + i + mx + my * stride,
722  ctx->height, stride, i + mx, j + my);
723  len--;
724  }
725  dst += stride * 4;
726  prev += stride * 4;
727  }
728  break;
729  case 2:
730  if (rle_decode(ctx, dst, decoded_size))
731  return AVERROR_INVALIDDATA;
732  memset(ctx->frm1, 0, ctx->frm1_size);
733  memset(ctx->frm2, 0, ctx->frm2_size);
734  break;
735  case 3:
736  case 4:
737  for (j = 0; j < height; j += 4) {
738  for (i = 0; i < width; i += 4) {
739  int code;
740  if (skip_run) {
741  skip_run--;
742  copy_block4(dst + i, prev + i, stride, stride, 4);
743  continue;
744  }
745  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
746  return AVERROR_INVALIDDATA;
747  code = bytestream2_get_byteu(&ctx->gb);
748  if (code == 0xFF) {
749  if (bytestream2_get_bytes_left(&ctx->gb) < 16)
750  return AVERROR_INVALIDDATA;
751  for (k = 0; k < 4; k++)
752  bytestream2_get_bufferu(&ctx->gb, dst + i + k * stride, 4);
753  } else if ((flags & 4) && (code == 0xFE)) {
754  if (bytestream2_get_bytes_left(&ctx->gb) < 4)
755  return AVERROR_INVALIDDATA;
756  for (k = 0; k < 4; k++)
757  memset(dst + i + k * stride, bytestream2_get_byteu(&ctx->gb), 4);
758  } else if ((flags & 4) && (code == 0xFD)) {
759  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
760  return AVERROR_INVALIDDATA;
761  t = bytestream2_get_byteu(&ctx->gb);
762  for (k = 0; k < 4; k++)
763  memset(dst + i + k * stride, t, 4);
764  } else if ((compr == 4) && (code == 0)) {
765  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
766  return AVERROR_INVALIDDATA;
767  skip_run = bytestream2_get_byteu(&ctx->gb) + 1;
768  i -= 4;
769  } else {
770  mx = c37_mv[(mvoff * 255 + code) * 2];
771  my = c37_mv[(mvoff * 255 + code) * 2 + 1];
772  codec37_mv(dst + i, prev + i + mx + my * stride,
773  ctx->height, stride, i + mx, j + my);
774  }
775  }
776  dst += stride * 4;
777  prev += stride * 4;
778  }
779  break;
780  default:
782  "Subcodec 37 compression %d", compr);
783  return AVERROR_PATCHWELCOME;
784  }
785 
786  return 0;
787 }
788 
789 static int process_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *prev1,
790  uint8_t *prev2, int stride, int tbl, int size)
791 {
792  int code, k, t;
793  uint8_t colors[2];
794  int8_t *pglyph;
795 
796  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
797  return AVERROR_INVALIDDATA;
798 
799  code = bytestream2_get_byteu(&ctx->gb);
800  if (code >= 0xF8) {
801  switch (code) {
802  case 0xFF:
803  if (size == 2) {
804  if (bytestream2_get_bytes_left(&ctx->gb) < 4)
805  return AVERROR_INVALIDDATA;
806  dst[0] = bytestream2_get_byteu(&ctx->gb);
807  dst[1] = bytestream2_get_byteu(&ctx->gb);
808  dst[0 + stride] = bytestream2_get_byteu(&ctx->gb);
809  dst[1 + stride] = bytestream2_get_byteu(&ctx->gb);
810  } else {
811  size >>= 1;
812  if (process_block(ctx, dst, prev1, prev2, stride, tbl, size))
813  return AVERROR_INVALIDDATA;
814  if (process_block(ctx, dst + size, prev1 + size, prev2 + size,
815  stride, tbl, size))
816  return AVERROR_INVALIDDATA;
817  dst += size * stride;
818  prev1 += size * stride;
819  prev2 += size * stride;
820  if (process_block(ctx, dst, prev1, prev2, stride, tbl, size))
821  return AVERROR_INVALIDDATA;
822  if (process_block(ctx, dst + size, prev1 + size, prev2 + size,
823  stride, tbl, size))
824  return AVERROR_INVALIDDATA;
825  }
826  break;
827  case 0xFE:
828  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
829  return AVERROR_INVALIDDATA;
830 
831  t = bytestream2_get_byteu(&ctx->gb);
832  for (k = 0; k < size; k++)
833  memset(dst + k * stride, t, size);
834  break;
835  case 0xFD:
836  if (bytestream2_get_bytes_left(&ctx->gb) < 3)
837  return AVERROR_INVALIDDATA;
838 
839  code = bytestream2_get_byteu(&ctx->gb);
840  pglyph = (size == 8) ? ctx->p8x8glyphs[code] : ctx->p4x4glyphs[code];
841  bytestream2_get_bufferu(&ctx->gb, colors, 2);
842 
843  for (k = 0; k < size; k++)
844  for (t = 0; t < size; t++)
845  dst[t + k * stride] = colors[!*pglyph++];
846  break;
847  case 0xFC:
848  for (k = 0; k < size; k++)
849  memcpy(dst + k * stride, prev1 + k * stride, size);
850  break;
851  default:
852  k = bytestream2_tell(&ctx->gb);
853  bytestream2_seek(&ctx->gb, tbl + (code & 7), SEEK_SET);
854  t = bytestream2_get_byte(&ctx->gb);
855  bytestream2_seek(&ctx->gb, k, SEEK_SET);
856  for (k = 0; k < size; k++)
857  memset(dst + k * stride, t, size);
858  }
859  } else {
860  int mx = motion_vectors[code][0];
861  int my = motion_vectors[code][1];
862  int index = prev2 - (const uint8_t *)ctx->frm2;
863 
864  av_assert2(index >= 0 && index < (ctx->buf_size >> 1));
865 
866  if (index < -mx - my * stride ||
867  (ctx->buf_size >> 1) - index < mx + size + (my + size - 1) * stride) {
868  av_log(ctx->avctx, AV_LOG_ERROR, "MV is invalid.\n");
869  return AVERROR_INVALIDDATA;
870  }
871 
872  for (k = 0; k < size; k++)
873  memcpy(dst + k * stride, prev2 + mx + (my + k) * stride, size);
874  }
875 
876  return 0;
877 }
878 
880 {
881  uint8_t *p1, *p2, *itbl = ctx->c47itbl;
882  int i, j;
883 
884  for (i = 0; i < 256; i++) {
885  p1 = p2 = itbl + i;
886  for (j = 256 - i; j; j--) {
887  *p1 = *p2 = bytestream2_get_byte(&ctx->gb);
888  p1 += 1;
889  p2 += 256;
890  }
891  itbl += 256;
892  }
893 }
894 
895 static void codec47_comp1(SANMVideoContext *ctx, uint8_t *dst_in, int width,
896  int height, ptrdiff_t stride)
897 {
898  uint8_t p1, *dst, *itbl = ctx->c47itbl;
899  uint16_t px;
900  int i, j;
901 
902  dst = dst_in + stride;
903  for (i = 0; i < height; i += 2) {
904  p1 = bytestream2_get_byte(&ctx->gb);
905  *dst++ = p1;
906  *dst++ = p1;
907  px = p1;
908  for (j = 2; j < width; j += 2) {
909  p1 = bytestream2_get_byte(&ctx->gb);
910  px = (px << 8) | p1;
911  *dst++ = itbl[px];
912  *dst++ = p1;
913  }
914  dst += stride;
915  }
916 
917  memcpy(dst_in, dst_in + stride, width);
918  dst = dst_in + stride + stride;
919  for (i = 2; i < height - 1; i += 2) {
920  for (j = 0; j < width; j++) {
921  px = (*(dst - stride) << 8) | *(dst + stride);
922  *dst++ = itbl[px];
923  }
924  dst += stride;
925  }
926 }
927 
928 static int old_codec47(SANMVideoContext *ctx, int top,
929  int left, int width, int height)
930 {
931  uint32_t decoded_size;
932  int i, j;
933  ptrdiff_t stride = ctx->pitch;
934  uint8_t *dst = (uint8_t *)ctx->frm0 + left + top * stride;
935  uint8_t *prev1 = (uint8_t *)ctx->frm1 + left + top * stride;
936  uint8_t *prev2 = (uint8_t *)ctx->frm2 + left + top * stride;
937  uint8_t auxcol[2];
938  int tbl_pos = bytestream2_tell(&ctx->gb);
939  int seq = bytestream2_get_le16(&ctx->gb);
940  int compr = bytestream2_get_byte(&ctx->gb);
941  int new_rot = bytestream2_get_byte(&ctx->gb);
942  int skip = bytestream2_get_byte(&ctx->gb);
943 
944  bytestream2_skip(&ctx->gb, 7);
945  auxcol[0] = bytestream2_get_byteu(&ctx->gb);
946  auxcol[1] = bytestream2_get_byteu(&ctx->gb);
947  decoded_size = bytestream2_get_le32(&ctx->gb);
948  bytestream2_skip(&ctx->gb, 8);
949 
950  if (decoded_size > ctx->height * stride - left - top * stride) {
951  decoded_size = ctx->height * stride - left - top * stride;
952  av_log(ctx->avctx, AV_LOG_WARNING, "Decoded size is too large.\n");
953  }
954 
955  if (skip & 1) {
956  if (bytestream2_get_bytes_left(&ctx->gb) < 0x8080)
957  return AVERROR_INVALIDDATA;
959  }
960  if (!seq) {
961  ctx->prev_seq = -1;
962  memset(prev1, auxcol[0], (ctx->height - top) * stride);
963  memset(prev2, auxcol[1], (ctx->height - top) * stride);
964  }
965 
966  switch (compr) {
967  case 0:
969  return AVERROR_INVALIDDATA;
970  for (j = 0; j < height; j++) {
972  dst += stride;
973  }
974  break;
975  case 1:
976  if (bytestream2_get_bytes_left(&ctx->gb) < ((width + 1) >> 1) * ((height + 1) >> 1))
977  return AVERROR_INVALIDDATA;
979  break;
980  case 2:
981  if (seq == ctx->prev_seq + 1) {
982  for (j = 0; j < height; j += 8) {
983  for (i = 0; i < width; i += 8)
984  if (process_block(ctx, dst + i, prev1 + i, prev2 + i, stride,
985  tbl_pos + 8, 8))
986  return AVERROR_INVALIDDATA;
987  dst += stride * 8;
988  prev1 += stride * 8;
989  prev2 += stride * 8;
990  }
991  }
992  break;
993  case 3:
994  memcpy(ctx->frm0, ctx->frm2, ctx->pitch * ctx->height);
995  break;
996  case 4:
997  memcpy(ctx->frm0, ctx->frm1, ctx->pitch * ctx->height);
998  break;
999  case 5:
1000  if (rle_decode(ctx, dst, decoded_size))
1001  return AVERROR_INVALIDDATA;
1002  break;
1003  default:
1005  "Subcodec 47 compression %d", compr);
1006  return AVERROR_PATCHWELCOME;
1007  }
1008  if (seq == ctx->prev_seq + 1)
1009  ctx->rotate_code = new_rot;
1010  else
1011  ctx->rotate_code = 0;
1012  ctx->prev_seq = seq;
1013 
1014  return 0;
1015 }
1016 
1017 // scale 4x4 input block to an 8x8 output block
1018 static void c48_4to8(uint8_t *dst, const uint8_t *src, const uint16_t w)
1019 {
1020  uint16_t p;
1021  // dst is always at least 16bit aligned
1022  for (int i = 0; i < 4; i++) {
1023  for (int j = 0; j < 8; j += 2) {
1024  p = *src++;
1025  p = (p << 8) | p;
1026  *((uint16_t *)(dst + w * 0 + j)) = p;
1027  *((uint16_t *)(dst + w * 1 + j)) = p;
1028  }
1029  dst += w * 2;
1030  }
1031 }
1032 
1033 static int codec48_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *db,
1034  const uint16_t w)
1035 {
1036  uint8_t opc, sb[16];
1037  int i, j, k, l;
1038  int16_t mvofs;
1039  uint32_t ofs;
1040 
1041  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1042  return 1;
1043 
1044  opc = bytestream2_get_byteu(&ctx->gb);
1045  switch (opc) {
1046  case 0xFF: // 1x1 -> 8x8 block scale
1047  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1048  return 1;
1049 
1050  opc = bytestream2_get_byteu(&ctx->gb);
1051  for (i = 0; i < 16; i++)
1052  sb[i] = opc;
1053  c48_4to8(dst, sb, w);
1054  break;
1055  case 0xFE: // 1x 8x8 copy from deltabuf, 16bit mv from source
1056  if (bytestream2_get_bytes_left(&ctx->gb) < 2)
1057  return 1;
1058  mvofs = bytestream2_get_le16(&ctx->gb);
1059  for (i = 0; i < 8; i++) {
1060  ofs = w * i;
1061  for (k = 0; k < 8; k++)
1062  *(dst + ofs + k) = *(db + ofs + k + mvofs);
1063  }
1064  break;
1065  case 0xFD: // 2x2 -> 8x8 block scale
1066  if (bytestream2_get_bytes_left(&ctx->gb) < 4)
1067  return 1;
1068  sb[ 5] = bytestream2_get_byteu(&ctx->gb);
1069  sb[ 7] = bytestream2_get_byteu(&ctx->gb);
1070  sb[13] = bytestream2_get_byteu(&ctx->gb);
1071  sb[15] = bytestream2_get_byteu(&ctx->gb);
1072 
1073  sb[0] = sb[1] = sb[4] = sb[5];
1074  sb[2] = sb[3] = sb[6] = sb[7];
1075  sb[8] = sb[9] = sb[12] = sb[13];
1076  sb[10] = sb[11] = sb[14] = sb[15];
1077  c48_4to8(dst, sb, w);
1078  break;
1079  case 0xFC: // 4x copy 4x4 block, per-block c37_mv from source
1080  if (bytestream2_get_bytes_left(&ctx->gb) < 4)
1081  return 1;
1082  for (i = 0; i < 8; i += 4) {
1083  for (k = 0; k < 8; k += 4) {
1084  opc = bytestream2_get_byteu(&ctx->gb);
1085  mvofs = c37_mv[opc * 2] + (c37_mv[opc * 2 + 1] * w);
1086  for (j = 0; j < 4; j++) {
1087  ofs = (w * (j + i)) + k;
1088  for (l = 0; l < 4; l++)
1089  *(dst + ofs + l) = *(db + ofs + l + mvofs);
1090  }
1091  }
1092  }
1093  break;
1094  case 0xFB: // Copy 4x 4x4 blocks, per-block mv from source
1095  if (bytestream2_get_bytes_left(&ctx->gb) < 8)
1096  return 1;
1097  for (i = 0; i < 8; i += 4) {
1098  for (k = 0; k < 8; k += 4) {
1099  mvofs = bytestream2_get_le16(&ctx->gb);
1100  for (j = 0; j < 4; j++) {
1101  ofs = (w * (j + i)) + k;
1102  for (l = 0; l < 4; l++)
1103  *(dst + ofs + l) = *(db + ofs + l + mvofs);
1104  }
1105  }
1106  }
1107  break;
1108  case 0xFA: // scale 4x4 input block to 8x8 dest block
1109  if (bytestream2_get_bytes_left(&ctx->gb) < 16)
1110  return 1;
1111  bytestream2_get_bufferu(&ctx->gb, sb, 16);
1112  c48_4to8(dst, sb, w);
1113  break;
1114  case 0xF9: // 16x 2x2 copy from delta, per-block c37_mv from source
1115  if (bytestream2_get_bytes_left(&ctx->gb) < 16)
1116  return 1;
1117  for (i = 0; i < 8; i += 2) {
1118  for (j = 0; j < 8; j += 2) {
1119  ofs = (w * i) + j;
1120  opc = bytestream2_get_byteu(&ctx->gb);
1121  mvofs = c37_mv[opc * 2] + (c37_mv[opc * 2 + 1] * w);
1122  for (l = 0; l < 2; l++) {
1123  *(dst + ofs + l + 0) = *(db + ofs + l + 0 + mvofs);
1124  *(dst + ofs + l + w) = *(db + ofs + l + w + mvofs);
1125  }
1126  }
1127  }
1128  break;
1129  case 0xF8: // 16x 2x2 blocks copy, 16bit mv from source
1130  if (bytestream2_get_bytes_left(&ctx->gb) < 32)
1131  return 1;
1132  for (i = 0; i < 8; i += 2) {
1133  for (j = 0; j < 8; j += 2) {
1134  ofs = w * i + j;
1135  mvofs = bytestream2_get_le16(&ctx->gb);
1136  for (l = 0; l < 2; l++) {
1137  *(dst + ofs + l + 0) = *(db + ofs + l + 0 + mvofs);
1138  *(dst + ofs + l + w) = *(db + ofs + l + w + mvofs);
1139  }
1140  }
1141  }
1142  break;
1143  case 0xF7: // copy 8x8 block from src to dest
1144  if (bytestream2_get_bytes_left(&ctx->gb) < 64)
1145  return 1;
1146  for (i = 0; i < 8; i++) {
1147  ofs = i * w;
1148  for (l = 0; l < 8; l++)
1149  *(dst + ofs + l) = bytestream2_get_byteu(&ctx->gb);
1150  }
1151  break;
1152  default: // copy 8x8 block from prev, c37_mv from source
1153  mvofs = c37_mv[opc * 2] + (c37_mv[opc * 2 + 1] * w);
1154  for (i = 0; i < 8; i++) {
1155  ofs = i * w;
1156  for (l = 0; l < 8; l++)
1157  *(dst + ofs + l) = *(db + ofs + l + mvofs);
1158  }
1159  break;
1160  }
1161  return 0;
1162 }
1163 
1165 {
1166  uint8_t *dst, *prev;
1167  int compr = bytestream2_get_byte(&ctx->gb);
1168  int mvidx = bytestream2_get_byte(&ctx->gb);
1169  int seq = bytestream2_get_le16(&ctx->gb);
1170  uint32_t decoded_size = bytestream2_get_le32(&ctx->gb);
1171  int i, j, flags;
1172 
1173  // all codec48 videos use 1, but just to be safe...
1174  if (mvidx != 1) {
1175  av_log(ctx->avctx, AV_LOG_ERROR, "Invalid motion base value %d.\n", mvidx);
1176  return AVERROR_INVALIDDATA;
1177  }
1178 
1179  bytestream2_skip(&ctx->gb, 4);
1180  flags = bytestream2_get_byte(&ctx->gb);
1181  bytestream2_skip(&ctx->gb, 3);
1182 
1183  if (flags & 8) {
1184  if (bytestream2_get_bytes_left(&ctx->gb) < 0x8080)
1185  return AVERROR_INVALIDDATA;
1187  }
1188 
1189  dst = (uint8_t*)ctx->frm0;
1190  prev = (uint8_t*)ctx->frm2;
1191 
1192  if (!seq) {
1193  ctx->prev_seq = -1;
1194  memset(prev, 0, ctx->aligned_height * width);
1195  }
1196 
1197  switch (compr) {
1198  case 0:
1200  return AVERROR_INVALIDDATA;
1201  for (j = 0; j < height; j++) {
1203  dst += width;
1204  }
1205  break;
1206  case 2:
1207  if (rle_decode(ctx, dst, decoded_size))
1208  return AVERROR_INVALIDDATA;
1209  break;
1210  case 3:
1211  if (seq == ctx->prev_seq + 1) {
1212  for (j = 0; j < height; j += 8) {
1213  for (i = 0; i < width; i += 8) {
1214  if (codec48_block(ctx, dst + i, prev + i, width))
1215  return AVERROR_INVALIDDATA;
1216  }
1217  dst += width * 8;
1218  prev += width * 8;
1219  }
1220  }
1221  break;
1222  case 5:
1223  if (bytestream2_get_bytes_left(&ctx->gb) < ((width + 1) >> 1) * ((height + 1) >> 1))
1224  return AVERROR_INVALIDDATA;
1226  break;
1227 
1228  default:
1230  "Subcodec 48 compression %d", compr);
1231  return AVERROR_PATCHWELCOME;
1232  }
1233  ctx->rotate_code = 1; // swap frm[0] and frm[2]
1234  ctx->prev_seq = seq;
1235  return 0;
1236 }
1237 
1239 {
1240  uint16_t codec = bytestream2_get_le16u(&ctx->gb);
1241  uint16_t left = bytestream2_get_le16u(&ctx->gb);
1242  uint16_t top = bytestream2_get_le16u(&ctx->gb);
1243  uint16_t w = bytestream2_get_le16u(&ctx->gb);
1244  uint16_t h = bytestream2_get_le16u(&ctx->gb);
1245 
1246  if (!w || !h) {
1247  av_log(ctx->avctx, AV_LOG_ERROR, "Dimensions are invalid.\n");
1248  return AVERROR_INVALIDDATA;
1249  }
1250 
1251  if (ctx->width < left + w || ctx->height < top + h) {
1252  int ret = ff_set_dimensions(ctx->avctx, FFMAX(left + w, ctx->width),
1253  FFMAX(top + h, ctx->height));
1254  if (ret < 0)
1255  return ret;
1256  init_sizes(ctx, FFMAX(left + w, ctx->width),
1257  FFMAX(top + h, ctx->height));
1258  if (init_buffers(ctx)) {
1259  av_log(ctx->avctx, AV_LOG_ERROR, "Error resizing buffers.\n");
1260  return AVERROR(ENOMEM);
1261  }
1262  }
1263  bytestream2_skip(&ctx->gb, 4);
1264 
1265  switch (codec) {
1266  case 1:
1267  case 3:
1268  return old_codec1(ctx, top, left, w, h);
1269  case 37:
1270  return old_codec37(ctx, top, left, w, h);
1271  case 47:
1272  return old_codec47(ctx, top, left, w, h);
1273  case 48:
1274  return old_codec48(ctx, w, h);
1275  default:
1276  avpriv_request_sample(ctx->avctx, "Subcodec %d", codec);
1277  return AVERROR_PATCHWELCOME;
1278  }
1279 }
1280 
1282 {
1283  int16_t *dp = ctx->delta_pal;
1284  uint32_t *pal = ctx->pal;
1285  uint16_t cmd;
1286  uint8_t c[3];
1287  int i, j;
1288 
1289  bytestream2_skip(&ctx->gb, 2);
1290  cmd = bytestream2_get_be16(&ctx->gb);
1291 
1292  if (cmd == 1) {
1293  for (i = 0; i < PALETTE_DELTA; i += 3) {
1294  c[0] = (*pal >> 16) & 0xFF;
1295  c[1] = (*pal >> 8) & 0xFF;
1296  c[2] = (*pal >> 0) & 0xFF;
1297  for (j = 0; j < 3; j++) {
1298  int cl = (c[j] * 129) + *dp++;
1299  c[j] = av_clip_uint8(cl / 128) & 0xFF;
1300  }
1301  *pal++ = 0xFFU << 24 | c[0] << 16 | c[1] << 8 | c[2];
1302  }
1303  } else if (cmd == 2) {
1304  if (size < PALETTE_DELTA * 2 + 4) {
1305  av_log(ctx->avctx, AV_LOG_ERROR,
1306  "Incorrect palette change block size %"PRIu32".\n", size);
1307  return AVERROR_INVALIDDATA;
1308  }
1309  for (i = 0; i < PALETTE_DELTA; i++)
1310  dp[i] = bytestream2_get_le16u(&ctx->gb);
1311 
1312  if (size >= PALETTE_DELTA * 2 + 4 + PALETTE_SIZE * 3) {
1313  for (i = 0; i < PALETTE_SIZE; i++)
1314  ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb);
1315  }
1316  }
1317  return 0;
1318 }
1319 
1321 {
1322  uint16_t *frm = ctx->frm0;
1323  int x, y;
1324 
1325  if (bytestream2_get_bytes_left(&ctx->gb) < ctx->width * ctx->height * 2) {
1326  av_log(ctx->avctx, AV_LOG_ERROR, "Insufficient data for raw frame.\n");
1327  return AVERROR_INVALIDDATA;
1328  }
1329  for (y = 0; y < ctx->height; y++) {
1330  for (x = 0; x < ctx->width; x++)
1331  frm[x] = bytestream2_get_le16u(&ctx->gb);
1332  frm += ctx->pitch;
1333  }
1334  return 0;
1335 }
1336 
1338 {
1339  avpriv_request_sample(ctx->avctx, "Unknown/unsupported compression type");
1340  return AVERROR_PATCHWELCOME;
1341 }
1342 
1343 static void copy_block(uint16_t *pdest, uint16_t *psrc, int block_size, ptrdiff_t pitch)
1344 {
1345  uint8_t *dst = (uint8_t *)pdest;
1346  uint8_t *src = (uint8_t *)psrc;
1347  ptrdiff_t stride = pitch * 2;
1348 
1349  switch (block_size) {
1350  case 2:
1351  copy_block4(dst, src, stride, stride, 2);
1352  break;
1353  case 4:
1354  copy_block8(dst, src, stride, stride, 4);
1355  break;
1356  case 8:
1357  copy_block16(dst, src, stride, stride, 8);
1358  break;
1359  }
1360 }
1361 
1362 static void fill_block(uint16_t *pdest, uint16_t color, int block_size, ptrdiff_t pitch)
1363 {
1364  int x, y;
1365 
1366  pitch -= block_size;
1367  for (y = 0; y < block_size; y++, pdest += pitch)
1368  for (x = 0; x < block_size; x++)
1369  *pdest++ = color;
1370 }
1371 
1372 static int draw_glyph(SANMVideoContext *ctx, uint16_t *dst, int index,
1373  uint16_t fg_color, uint16_t bg_color, int block_size,
1374  ptrdiff_t pitch)
1375 {
1376  int8_t *pglyph;
1377  uint16_t colors[2] = { fg_color, bg_color };
1378  int x, y;
1379 
1380  if (index >= NGLYPHS) {
1381  av_log(ctx->avctx, AV_LOG_ERROR, "Ignoring nonexistent glyph #%u.\n", index);
1382  return AVERROR_INVALIDDATA;
1383  }
1384 
1385  pglyph = block_size == 8 ? ctx->p8x8glyphs[index] : ctx->p4x4glyphs[index];
1386  pitch -= block_size;
1387 
1388  for (y = 0; y < block_size; y++, dst += pitch)
1389  for (x = 0; x < block_size; x++)
1390  *dst++ = colors[*pglyph++];
1391  return 0;
1392 }
1393 
1394 static int opcode_0xf7(SANMVideoContext *ctx, int cx, int cy, int block_size, ptrdiff_t pitch)
1395 {
1396  uint16_t *dst = ctx->frm0 + cx + cy * ctx->pitch;
1397 
1398  if (block_size == 2) {
1399  uint32_t indices;
1400 
1401  if (bytestream2_get_bytes_left(&ctx->gb) < 4)
1402  return AVERROR_INVALIDDATA;
1403 
1404  indices = bytestream2_get_le32u(&ctx->gb);
1405  dst[0] = ctx->codebook[indices & 0xFF];
1406  indices >>= 8;
1407  dst[1] = ctx->codebook[indices & 0xFF];
1408  indices >>= 8;
1409  dst[pitch] = ctx->codebook[indices & 0xFF];
1410  indices >>= 8;
1411  dst[pitch + 1] = ctx->codebook[indices & 0xFF];
1412  } else {
1413  uint16_t fgcolor, bgcolor;
1414  int glyph;
1415 
1416  if (bytestream2_get_bytes_left(&ctx->gb) < 3)
1417  return AVERROR_INVALIDDATA;
1418 
1419  glyph = bytestream2_get_byteu(&ctx->gb);
1420  bgcolor = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
1421  fgcolor = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
1422 
1423  draw_glyph(ctx, dst, glyph, fgcolor, bgcolor, block_size, pitch);
1424  }
1425  return 0;
1426 }
1427 
1428 static int opcode_0xf8(SANMVideoContext *ctx, int cx, int cy, int block_size, ptrdiff_t pitch)
1429 {
1430  uint16_t *dst = ctx->frm0 + cx + cy * ctx->pitch;
1431 
1432  if (block_size == 2) {
1433  if (bytestream2_get_bytes_left(&ctx->gb) < 8)
1434  return AVERROR_INVALIDDATA;
1435 
1436  dst[0] = bytestream2_get_le16u(&ctx->gb);
1437  dst[1] = bytestream2_get_le16u(&ctx->gb);
1438  dst[pitch] = bytestream2_get_le16u(&ctx->gb);
1439  dst[pitch + 1] = bytestream2_get_le16u(&ctx->gb);
1440  } else {
1441  uint16_t fgcolor, bgcolor;
1442  int glyph;
1443 
1444  if (bytestream2_get_bytes_left(&ctx->gb) < 5)
1445  return AVERROR_INVALIDDATA;
1446 
1447  glyph = bytestream2_get_byteu(&ctx->gb);
1448  bgcolor = bytestream2_get_le16u(&ctx->gb);
1449  fgcolor = bytestream2_get_le16u(&ctx->gb);
1450 
1451  draw_glyph(ctx, dst, glyph, fgcolor, bgcolor, block_size, pitch);
1452  }
1453  return 0;
1454 }
1455 
1456 static int good_mvec(SANMVideoContext *ctx, int cx, int cy, int mx, int my,
1457  int block_size)
1458 {
1459  int start_pos = cx + mx + (cy + my) * ctx->pitch;
1460  int end_pos = start_pos + (block_size - 1) * (ctx->pitch + 1);
1461 
1462  int good = start_pos >= 0 && end_pos < (ctx->buf_size >> 1);
1463 
1464  if (!good)
1465  av_log(ctx->avctx, AV_LOG_ERROR,
1466  "Ignoring invalid motion vector (%i, %i)->(%u, %u), block size = %u\n",
1467  cx + mx, cy + my, cx, cy, block_size);
1468 
1469  return good;
1470 }
1471 
1472 static int codec2subblock(SANMVideoContext *ctx, int cx, int cy, int blk_size)
1473 {
1474  int16_t mx, my, index;
1475  int opcode;
1476 
1477  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1478  return AVERROR_INVALIDDATA;
1479 
1480  opcode = bytestream2_get_byteu(&ctx->gb);
1481 
1482  switch (opcode) {
1483  default:
1484  mx = motion_vectors[opcode][0];
1485  my = motion_vectors[opcode][1];
1486 
1487  if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
1488  copy_block(ctx->frm0 + cx + ctx->pitch * cy,
1489  ctx->frm2 + cx + mx + ctx->pitch * (cy + my),
1490  blk_size, ctx->pitch);
1491  }
1492  break;
1493  case 0xF5:
1494  if (bytestream2_get_bytes_left(&ctx->gb) < 2)
1495  return AVERROR_INVALIDDATA;
1496  index = bytestream2_get_le16u(&ctx->gb);
1497 
1498  mx = index % ctx->width;
1499  my = index / ctx->width;
1500 
1501  if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
1502  copy_block(ctx->frm0 + cx + ctx->pitch * cy,
1503  ctx->frm2 + cx + mx + ctx->pitch * (cy + my),
1504  blk_size, ctx->pitch);
1505  }
1506  break;
1507  case 0xF6:
1508  copy_block(ctx->frm0 + cx + ctx->pitch * cy,
1509  ctx->frm1 + cx + ctx->pitch * cy,
1510  blk_size, ctx->pitch);
1511  break;
1512  case 0xF7:
1513  opcode_0xf7(ctx, cx, cy, blk_size, ctx->pitch);
1514  break;
1515 
1516  case 0xF8:
1517  opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch);
1518  break;
1519  case 0xF9:
1520  case 0xFA:
1521  case 0xFB:
1522  case 0xFC:
1523  fill_block(ctx->frm0 + cx + cy * ctx->pitch,
1524  ctx->small_codebook[opcode - 0xf9], blk_size, ctx->pitch);
1525  break;
1526  case 0xFD:
1527  if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1528  return AVERROR_INVALIDDATA;
1529  fill_block(ctx->frm0 + cx + cy * ctx->pitch,
1530  ctx->codebook[bytestream2_get_byteu(&ctx->gb)], blk_size, ctx->pitch);
1531  break;
1532  case 0xFE:
1533  if (bytestream2_get_bytes_left(&ctx->gb) < 2)
1534  return AVERROR_INVALIDDATA;
1535  fill_block(ctx->frm0 + cx + cy * ctx->pitch,
1536  bytestream2_get_le16u(&ctx->gb), blk_size, ctx->pitch);
1537  break;
1538  case 0xFF:
1539  if (blk_size == 2) {
1540  opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch);
1541  } else {
1542  blk_size >>= 1;
1543  if (codec2subblock(ctx, cx, cy, blk_size))
1544  return AVERROR_INVALIDDATA;
1545  if (codec2subblock(ctx, cx + blk_size, cy, blk_size))
1546  return AVERROR_INVALIDDATA;
1547  if (codec2subblock(ctx, cx, cy + blk_size, blk_size))
1548  return AVERROR_INVALIDDATA;
1549  if (codec2subblock(ctx, cx + blk_size, cy + blk_size, blk_size))
1550  return AVERROR_INVALIDDATA;
1551  }
1552  break;
1553  }
1554  return 0;
1555 }
1556 
1558 {
1559  int cx, cy, ret;
1560 
1561  for (cy = 0; cy < ctx->aligned_height; cy += 8)
1562  for (cx = 0; cx < ctx->aligned_width; cx += 8)
1563  if (ret = codec2subblock(ctx, cx, cy, 8))
1564  return ret;
1565 
1566  return 0;
1567 }
1568 
1570 {
1571  memcpy(ctx->frm0, ctx->frm2, ctx->frm2_size);
1572  return 0;
1573 }
1574 
1576 {
1577  memcpy(ctx->frm0, ctx->frm1, ctx->frm1_size);
1578  return 0;
1579 }
1580 
1582 {
1583 #if HAVE_BIGENDIAN
1584  uint16_t *frm;
1585  int npixels;
1586 #endif
1587  uint8_t *dst = (uint8_t*)ctx->frm0;
1588 
1589  if (rle_decode(ctx, dst, ctx->buf_size))
1590  return AVERROR_INVALIDDATA;
1591 
1592 #if HAVE_BIGENDIAN
1593  npixels = ctx->npixels;
1594  frm = ctx->frm0;
1595  while (npixels--) {
1596  *frm = av_bswap16(*frm);
1597  frm++;
1598  }
1599 #endif
1600 
1601  return 0;
1602 }
1603 
1605 {
1606  int npixels = ctx->npixels;
1607  uint16_t *frm = ctx->frm0;
1608 
1609  if (bytestream2_get_bytes_left(&ctx->gb) < npixels) {
1610  av_log(ctx->avctx, AV_LOG_ERROR, "Insufficient data for frame.\n");
1611  return AVERROR_INVALIDDATA;
1612  }
1613  while (npixels--)
1614  *frm++ = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
1615 
1616  return 0;
1617 }
1618 
1620 {
1621  uint16_t *pdest = ctx->frm0;
1622  uint8_t *rsrc;
1623  long npixels = ctx->npixels;
1624 
1625  av_fast_malloc(&ctx->rle_buf, &ctx->rle_buf_size, npixels);
1626  if (!ctx->rle_buf) {
1627  av_log(ctx->avctx, AV_LOG_ERROR, "RLE buffer allocation failed.\n");
1628  return AVERROR(ENOMEM);
1629  }
1630  rsrc = ctx->rle_buf;
1631 
1632  if (rle_decode(ctx, rsrc, npixels))
1633  return AVERROR_INVALIDDATA;
1634 
1635  while (npixels--)
1636  *pdest++ = ctx->codebook[*rsrc++];
1637 
1638  return 0;
1639 }
1640 
1642 
1643 static const frm_decoder v1_decoders[] = {
1646 };
1647 
1649 {
1650  int i, ret;
1651 
1652  if ((ret = bytestream2_get_bytes_left(&ctx->gb)) < 560) {
1653  av_log(ctx->avctx, AV_LOG_ERROR, "Input frame too short (%d bytes).\n",
1654  ret);
1655  return AVERROR_INVALIDDATA;
1656  }
1657  bytestream2_skip(&ctx->gb, 8); // skip pad
1658 
1659  hdr->width = bytestream2_get_le32u(&ctx->gb);
1660  hdr->height = bytestream2_get_le32u(&ctx->gb);
1661 
1662  if (hdr->width != ctx->width || hdr->height != ctx->height) {
1663  avpriv_report_missing_feature(ctx->avctx, "Variable size frames");
1664  return AVERROR_PATCHWELCOME;
1665  }
1666 
1667  hdr->seq_num = bytestream2_get_le16u(&ctx->gb);
1668  hdr->codec = bytestream2_get_byteu(&ctx->gb);
1669  hdr->rotate_code = bytestream2_get_byteu(&ctx->gb);
1670 
1671  bytestream2_skip(&ctx->gb, 4); // skip pad
1672 
1673  for (i = 0; i < 4; i++)
1674  ctx->small_codebook[i] = bytestream2_get_le16u(&ctx->gb);
1675  hdr->bg_color = bytestream2_get_le16u(&ctx->gb);
1676 
1677  bytestream2_skip(&ctx->gb, 2); // skip pad
1678 
1679  hdr->rle_output_size = bytestream2_get_le32u(&ctx->gb);
1680  for (i = 0; i < 256; i++)
1681  ctx->codebook[i] = bytestream2_get_le16u(&ctx->gb);
1682 
1683  bytestream2_skip(&ctx->gb, 8); // skip pad
1684 
1685  return 0;
1686 }
1687 
1688 static void fill_frame(uint16_t *pbuf, int buf_size, uint16_t color)
1689 {
1690  if (buf_size--) {
1691  *pbuf++ = color;
1692  av_memcpy_backptr((uint8_t*)pbuf, 2, 2*buf_size);
1693  }
1694 }
1695 
1697 {
1698  uint8_t *dst;
1699  const uint8_t *src = (uint8_t*) ctx->frm0;
1700  int ret, height = ctx->height;
1701  ptrdiff_t dstpitch, srcpitch = ctx->pitch * (hdr ? sizeof(ctx->frm0[0]) : 1);
1702 
1703  if ((ret = ff_get_buffer(ctx->avctx, ctx->frame, 0)) < 0)
1704  return ret;
1705 
1706  dst = ctx->frame->data[0];
1707  dstpitch = ctx->frame->linesize[0];
1708 
1709  while (height--) {
1710  memcpy(dst, src, srcpitch);
1711  src += srcpitch;
1712  dst += dstpitch;
1713  }
1714 
1715  return 0;
1716 }
1717 
1719  int *got_frame_ptr, AVPacket *pkt)
1720 {
1721  SANMVideoContext *ctx = avctx->priv_data;
1722  int i, ret;
1723 
1724  ctx->frame = frame;
1725  bytestream2_init(&ctx->gb, pkt->data, pkt->size);
1726 
1727  if (!ctx->version) {
1728  int to_store = 0;
1729 
1730  while (bytestream2_get_bytes_left(&ctx->gb) >= 8) {
1731  uint32_t sig, size;
1732  int pos;
1733 
1734  sig = bytestream2_get_be32u(&ctx->gb);
1735  size = bytestream2_get_be32u(&ctx->gb);
1736  pos = bytestream2_tell(&ctx->gb);
1737 
1738  if (bytestream2_get_bytes_left(&ctx->gb) < size) {
1739  av_log(avctx, AV_LOG_ERROR, "Incorrect chunk size %"PRIu32".\n", size);
1740  break;
1741  }
1742  switch (sig) {
1743  case MKBETAG('N', 'P', 'A', 'L'):
1744  if (size != PALETTE_SIZE * 3) {
1745  av_log(avctx, AV_LOG_ERROR,
1746  "Incorrect palette block size %"PRIu32".\n", size);
1747  return AVERROR_INVALIDDATA;
1748  }
1749  for (i = 0; i < PALETTE_SIZE; i++)
1750  ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb);
1751  break;
1752  case MKBETAG('F', 'O', 'B', 'J'):
1753  if (size < 16)
1754  return AVERROR_INVALIDDATA;
1755  if (ret = process_frame_obj(ctx))
1756  return ret;
1757  break;
1758  case MKBETAG('X', 'P', 'A', 'L'):
1759  if (ret = process_xpal(ctx, size))
1760  return ret;
1761  break;
1762  case MKBETAG('S', 'T', 'O', 'R'):
1763  to_store = 1;
1764  break;
1765  case MKBETAG('F', 'T', 'C', 'H'):
1766  memcpy(ctx->frm0, ctx->stored_frame, ctx->buf_size);
1767  break;
1768  default:
1769  bytestream2_skip(&ctx->gb, size);
1770  av_log(avctx, AV_LOG_DEBUG,
1771  "Unknown/unsupported chunk %"PRIx32".\n", sig);
1772  break;
1773  }
1774 
1775  bytestream2_seek(&ctx->gb, pos + size, SEEK_SET);
1776  if (size & 1)
1777  bytestream2_skip(&ctx->gb, 1);
1778  }
1779  if (to_store)
1780  memcpy(ctx->stored_frame, ctx->frm0, ctx->buf_size);
1781  if ((ret = copy_output(ctx, NULL)))
1782  return ret;
1783  memcpy(ctx->frame->data[1], ctx->pal, 1024);
1784  } else {
1786 
1787  if ((ret = read_frame_header(ctx, &header)))
1788  return ret;
1789 
1790  ctx->rotate_code = header.rotate_code;
1791  if (!header.seq_num) {
1792  ctx->frame->flags |= AV_FRAME_FLAG_KEY;
1793  ctx->frame->pict_type = AV_PICTURE_TYPE_I;
1794  fill_frame(ctx->frm1, ctx->npixels, header.bg_color);
1795  fill_frame(ctx->frm2, ctx->npixels, header.bg_color);
1796  } else {
1797  ctx->frame->flags &= ~AV_FRAME_FLAG_KEY;
1798  ctx->frame->pict_type = AV_PICTURE_TYPE_P;
1799  }
1800 
1801  if (header.codec < FF_ARRAY_ELEMS(v1_decoders)) {
1802  if ((ret = v1_decoders[header.codec](ctx))) {
1803  av_log(avctx, AV_LOG_ERROR,
1804  "Subcodec %d: error decoding frame.\n", header.codec);
1805  return ret;
1806  }
1807  } else {
1808  avpriv_request_sample(avctx, "Subcodec %d", header.codec);
1809  return AVERROR_PATCHWELCOME;
1810  }
1811 
1812  if ((ret = copy_output(ctx, &header)))
1813  return ret;
1814  }
1815  if (ctx->rotate_code)
1816  rotate_bufs(ctx, ctx->rotate_code);
1817 
1818  *got_frame_ptr = 1;
1819 
1820  return pkt->size;
1821 }
1822 
1824  .p.name = "sanm",
1825  CODEC_LONG_NAME("LucasArts SANM/Smush video"),
1826  .p.type = AVMEDIA_TYPE_VIDEO,
1827  .p.id = AV_CODEC_ID_SANM,
1828  .priv_data_size = sizeof(SANMVideoContext),
1829  .init = decode_init,
1830  .close = decode_end,
1832  .p.capabilities = AV_CODEC_CAP_DR1,
1833 };
SANMVideoContext::width
int width
Definition: sanm.c:272
codec47_read_interptable
static void codec47_read_interptable(SANMVideoContext *ctx)
Definition: sanm.c:879
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:215
AV_CODEC_ID_SANM
@ AV_CODEC_ID_SANM
Definition: codec_id.h:236
motion_vectors
static const int8_t motion_vectors[256][2]
Definition: sanm.c:53
decode_0
static int decode_0(SANMVideoContext *ctx)
Definition: sanm.c:1320
BOTTOM_EDGE
@ BOTTOM_EDGE
Definition: sanm.c:308
SANMVideoContext::rle_buf
uint8_t * rle_buf
Definition: sanm.c:282
decode_5
static int decode_5(SANMVideoContext *ctx)
Definition: sanm.c:1581
fill_block
static void fill_block(uint16_t *pdest, uint16_t color, int block_size, ptrdiff_t pitch)
Definition: sanm.c:1362
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
make_glyphs
static void make_glyphs(int8_t *pglyphs, const int8_t *xvec, const int8_t *yvec, const int side_length)
Construct glyphs by iterating through vector coordinates.
Definition: sanm.c:386
color
Definition: vf_paletteuse.c:513
process_block
static int process_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *prev1, uint8_t *prev2, int stride, int tbl, int size)
Definition: sanm.c:789
GetByteContext
Definition: bytestream.h:33
SANMVideoContext::pal
uint32_t pal[PALETTE_SIZE]
Definition: sanm.c:268
SANMFrameHeader
Definition: sanm.c:297
SANMVideoContext::stored_frame
uint8_t * stored_frame
Definition: sanm.c:278
SANMVideoContext::aligned_height
int aligned_height
Definition: sanm.c:273
SANMVideoContext::p4x4glyphs
int8_t p4x4glyphs[NGLYPHS][16]
Definition: sanm.c:292
SANMVideoContext::frm0
uint16_t * frm0
Definition: sanm.c:277
SANMFrameHeader::bg_color
uint16_t bg_color
Definition: sanm.c:300
good_mvec
static int good_mvec(SANMVideoContext *ctx, int cx, int cy, int mx, int my, int block_size)
Definition: sanm.c:1456
out_size
int out_size
Definition: movenc.c:56
bytestream2_seek
static av_always_inline int bytestream2_seek(GetByteContext *g, int offset, int whence)
Definition: bytestream.h:212
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:403
w
uint8_t w
Definition: llviddspenc.c:38
AVPacket::data
uint8_t * data
Definition: packet.h:539
decode_end
static av_cold int decode_end(AVCodecContext *avctx)
Definition: sanm.c:523
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
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
decode_3
static int decode_3(SANMVideoContext *ctx)
Definition: sanm.c:1569
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:94
ff_sanm_decoder
const FFCodec ff_sanm_decoder
Definition: sanm.c:1823
old_codec37
static int old_codec37(SANMVideoContext *ctx, int top, int left, int width, int height)
Definition: sanm.c:624
bytestream2_skip
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:168
SANMVideoContext::frame
AVFrame * frame
Definition: sanm.c:276
SANMFrameHeader::codec
int codec
Definition: sanm.c:298
mx
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t mx
Definition: dsp.h:53
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:131
LEFT_EDGE
@ LEFT_EDGE
Definition: sanm.c:305
old_codec47
static int old_codec47(SANMVideoContext *ctx, int top, int left, int width, int height)
Definition: sanm.c:928
glyph8_x
static const int8_t glyph8_x[GLYPH_COORD_VECT_SIZE]
Definition: sanm.c:45
SANMFrameHeader::rotate_code
int rotate_code
Definition: sanm.c:298
SANMVideoContext::gb
GetByteContext gb
Definition: sanm.c:265
destroy_buffers
static void destroy_buffers(SANMVideoContext *ctx)
Definition: sanm.c:451
val
static double val(void *priv, double ch)
Definition: aeval.c:77
decode_2
static int decode_2(SANMVideoContext *ctx)
Definition: sanm.c:1557
SANMVideoContext::small_codebook
uint16_t small_codebook[4]
Definition: sanm.c:290
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
TOP_EDGE
@ TOP_EDGE
Definition: sanm.c:306
avassert.h
old_codec1
static int old_codec1(SANMVideoContext *ctx, int top, int left, int width, int height)
Definition: sanm.c:558
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:209
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_cold
#define av_cold
Definition: attributes.h:90
SANMFrameHeader::width
uint32_t width
Definition: sanm.c:301
AV_FRAME_FLAG_KEY
#define AV_FRAME_FLAG_KEY
A flag to mark frames that are keyframes.
Definition: frame.h:654
av_memcpy_backptr
void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
Overlapping memcpy() implementation.
Definition: mem.c:447
AVCodecContext::extradata_size
int extradata_size
Definition: avcodec.h:538
codec48_block
static int codec48_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *db, const uint16_t w)
Definition: sanm.c:1033
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:311
SANMFrameHeader::rle_output_size
int rle_output_size
Definition: sanm.c:298
decode_6
static int decode_6(SANMVideoContext *ctx)
Definition: sanm.c:1604
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1451
c48_4to8
static void c48_4to8(uint8_t *dst, const uint8_t *src, const uint16_t w)
Definition: sanm.c:1018
SANMVideoContext::npixels
long npixels
Definition: sanm.c:287
codec47_comp1
static void codec47_comp1(SANMVideoContext *ctx, uint8_t *dst_in, int width, int height, ptrdiff_t stride)
Definition: sanm.c:895
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:230
opcode_0xf8
static int opcode_0xf8(SANMVideoContext *ctx, int cx, int cy, int block_size, ptrdiff_t pitch)
Definition: sanm.c:1428
ctx
AVFormatContext * ctx
Definition: movenc.c:49
SANMVideoContext::stored_frame_size
uint32_t stored_frame_size
Definition: sanm.c:280
decode.h
AV_RL16
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_RL16
Definition: bytestream.h:94
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:296
my
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t my
Definition: dsp.h:53
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
NULL
#define NULL
Definition: coverity.c:32
SANMFrameHeader::height
uint32_t height
Definition: sanm.c:301
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:64
run
uint8_t run
Definition: svq3.c:204
SANMVideoContext::aligned_width
int aligned_width
Definition: sanm.c:273
SANMVideoContext::avctx
AVCodecContext * avctx
Definition: sanm.c:264
SANMVideoContext::subversion
int subversion
Definition: sanm.c:267
draw_glyph
static int draw_glyph(SANMVideoContext *ctx, uint16_t *dst, int index, uint16_t fg_color, uint16_t bg_color, int block_size, ptrdiff_t pitch)
Definition: sanm.c:1372
AV_PICTURE_TYPE_I
@ AV_PICTURE_TYPE_I
Intra.
Definition: avutil.h:279
decode_nop
static int decode_nop(SANMVideoContext *ctx)
Definition: sanm.c:1337
bytestream2_get_buffer
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:267
PALETTE_SIZE
#define PALETTE_SIZE
Definition: sanm.c:34
SANMVideoContext::frm1_size
uint32_t frm1_size
Definition: sanm.c:279
SANMVideoContext::frm1
uint16_t * frm1
Definition: sanm.c:277
rotate_bufs
static void rotate_bufs(SANMVideoContext *ctx, int rotate_code)
Definition: sanm.c:482
SANMVideoContext::c47itbl
uint8_t c47itbl[0x10000]
Definition: sanm.c:294
index
int index
Definition: gxfenc.c:90
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
bytestream2_get_bytes_left
static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:158
bytestream2_tell
static av_always_inline int bytestream2_tell(GetByteContext *g)
Definition: bytestream.h:192
glyph4_y
static const int8_t glyph4_y[GLYPH_COORD_VECT_SIZE]
Definition: sanm.c:41
NGLYPHS
#define NGLYPHS
Definition: sanm.c:32
SANMVideoContext::frm2_size
uint32_t frm2_size
Definition: sanm.c:279
ff_get_buffer
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1697
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:368
AV_CODEC_CAP_DR1
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:52
AVPacket::size
int size
Definition: packet.h:540
SANMVideoContext
Definition: sanm.c:263
height
#define height
Definition: dsp.h:85
codec37_mv
static void codec37_mv(uint8_t *dst, const uint8_t *src, int height, int stride, int x, int y)
Definition: sanm.c:605
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:83
decode_4
static int decode_4(SANMVideoContext *ctx)
Definition: sanm.c:1575
size
int size
Definition: twinvq_data.h:10344
color
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:94
MKBETAG
#define MKBETAG(a, b, c, d)
Definition: macros.h:56
avpriv_report_missing_feature
void avpriv_report_missing_feature(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
SANMVideoContext::version
int version
Definition: sanm.c:267
header
static const uint8_t header[24]
Definition: sdr2.c:68
decode_init
static av_cold int decode_init(AVCodecContext *avctx)
Definition: sanm.c:489
rle_decode
static int rle_decode(SANMVideoContext *ctx, uint8_t *dst, const int out_size)
Definition: sanm.c:532
PALETTE_DELTA
#define PALETTE_DELTA
Definition: sanm.c:35
flag
#define flag(name)
Definition: cbs_av1.c:474
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:67
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
fill_frame
static void fill_frame(uint16_t *pbuf, int buf_size, uint16_t color)
Definition: sanm.c:1688
copy_block.h
copy_block
static void copy_block(uint16_t *pdest, uint16_t *psrc, int block_size, ptrdiff_t pitch)
Definition: sanm.c:1343
AVCodecContext::extradata
uint8_t * extradata
Out-of-band global headers that may be used by some codecs.
Definition: avcodec.h:537
process_xpal
static int process_xpal(SANMVideoContext *ctx, int size)
Definition: sanm.c:1281
SANMFrameHeader::seq_num
int seq_num
Definition: sanm.c:298
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:194
len
int len
Definition: vorbis_enc_data.h:426
AVCodecContext::height
int height
Definition: avcodec.h:632
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:671
AV_PIX_FMT_RGB565
#define AV_PIX_FMT_RGB565
Definition: pixfmt.h:497
avcodec.h
stride
#define stride
Definition: h264pred_template.c:536
SANMVideoContext::codebook
uint16_t codebook[256]
Definition: sanm.c:289
read_frame_header
static int read_frame_header(SANMVideoContext *ctx, SANMFrameHeader *hdr)
Definition: sanm.c:1648
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:264
SANMVideoContext::frm2
uint16_t * frm2
Definition: sanm.c:277
DIR_RIGHT
@ DIR_RIGHT
Definition: sanm.c:315
pos
unsigned int pos
Definition: spdifenc.c:414
process_frame_obj
static int process_frame_obj(SANMVideoContext *ctx)
Definition: sanm.c:1238
c37_mv
static const int8_t c37_mv[]
Definition: sanm.c:107
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
AVCodecContext
main external API structure.
Definition: avcodec.h:451
copy_output
static int copy_output(SANMVideoContext *ctx, SANMFrameHeader *hdr)
Definition: sanm.c:1696
SANMVideoContext::rle_buf_size
unsigned int rle_buf_size
Definition: sanm.c:283
SANMVideoContext::buf_size
long buf_size
Definition: sanm.c:287
av_fast_padded_mallocz
void av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size)
Same behaviour av_fast_padded_malloc except that buffer will always be 0-initialized after call.
Definition: utils.c:65
which_direction
static enum GlyphDir which_direction(enum GlyphEdge edge0, enum GlyphEdge edge1)
Definition: sanm.c:343
old_codec48
static int old_codec48(SANMVideoContext *ctx, int width, int height)
Definition: sanm.c:1164
av_clip_uint8
#define av_clip_uint8
Definition: common.h:106
RIGHT_EDGE
@ RIGHT_EDGE
Definition: sanm.c:307
AV_PICTURE_TYPE_P
@ AV_PICTURE_TYPE_P
Predicted.
Definition: avutil.h:280
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
SANMVideoContext::p8x8glyphs
int8_t p8x8glyphs[NGLYPHS][64]
Definition: sanm.c:293
mem.h
bytestream2_get_bufferu
static av_always_inline unsigned int bytestream2_get_bufferu(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:277
avpriv_request_sample
#define avpriv_request_sample(...)
Definition: tableprint_vlc.h:36
opcode_0xf7
static int opcode_0xf7(SANMVideoContext *ctx, int cx, int cy, int block_size, ptrdiff_t pitch)
Definition: sanm.c:1394
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AVPacket
This structure stores compressed data.
Definition: packet.h:516
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:478
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
av_fast_malloc
void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
Allocate a buffer, reusing the given one if large enough.
Definition: mem.c:557
codec2subblock
static int codec2subblock(SANMVideoContext *ctx, int cx, int cy, int blk_size)
Definition: sanm.c:1472
frm_decoder
int(* frm_decoder)(SANMVideoContext *ctx)
Definition: sanm.c:1641
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:632
bytestream.h
bytestream2_init
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:482
DIR_UP
@ DIR_UP
Definition: sanm.c:314
v1_decoders
static const frm_decoder v1_decoders[]
Definition: sanm.c:1643
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
h
h
Definition: vp9dsp_template.c:2070
SANMVideoContext::delta_pal
int16_t delta_pal[PALETTE_DELTA]
Definition: sanm.c:269
NO_DIR
@ NO_DIR
Definition: sanm.c:317
width
#define width
Definition: dsp.h:85
av_bswap16
#define av_bswap16
Definition: bswap.h:28
SANMVideoContext::rotate_code
int rotate_code
Definition: sanm.c:285
SANMVideoContext::pitch
ptrdiff_t pitch
Definition: sanm.c:271
skip
static void BS_FUNC() skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
Definition: bitstream_template.h:375
src
#define src
Definition: vp8dsp.c:248
SANMVideoContext::frm0_size
uint32_t frm0_size
Definition: sanm.c:279
SANMVideoContext::prev_seq
int prev_seq
Definition: sanm.c:274
SANMVideoContext::height
int height
Definition: sanm.c:272
decode_8
static int decode_8(SANMVideoContext *ctx)
Definition: sanm.c:1619
decode_frame
static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *pkt)
Definition: sanm.c:1718
init_buffers
static av_cold int init_buffers(SANMVideoContext *ctx)
Definition: sanm.c:464