]> git.sesse.net Git - ffmpeg/blob - libavcodec/sanm.c
Merge commit '68395f8c99393c281a08139d20a7a04398b2fd04'
[ffmpeg] / libavcodec / sanm.c
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/bswap.h"
25 #include "libavutil/imgutils.h"
26
27 #include "avcodec.h"
28 #include "bytestream.h"
29 #include "copy_block.h"
30 #include "internal.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 {
264     AVCodecContext *avctx;
265     GetByteContext gb;
266
267     int version, subversion;
268     uint32_t pal[PALETTE_SIZE];
269     int16_t delta_pal[PALETTE_DELTA];
270
271     int pitch;
272     int width, height;
273     int aligned_width, aligned_height;
274     int prev_seq;
275
276     AVFrame *frame;
277     uint16_t *frm0, *frm1, *frm2;
278     uint8_t *stored_frame;
279     uint32_t frm0_size, frm1_size, frm2_size;
280     uint32_t stored_frame_size;
281
282     uint8_t *rle_buf;
283     unsigned int rle_buf_size;
284
285     int rotate_code;
286
287     long npixels, buf_size;
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 } SANMVideoContext;
295
296 typedef struct SANMFrameHeader {
297     int seq_num, codec, rotate_code, rle_output_size;
298
299     uint16_t bg_color;
300     uint32_t width, height;
301 } SANMFrameHeader;
302
303 enum GlyphEdge {
304     LEFT_EDGE,
305     TOP_EDGE,
306     RIGHT_EDGE,
307     BOTTOM_EDGE,
308     NO_EDGE
309 };
310
311 enum GlyphDir {
312     DIR_LEFT,
313     DIR_UP,
314     DIR_RIGHT,
315     DIR_DOWN,
316     NO_DIR
317 };
318
319 /**
320  * Return enum GlyphEdge of box where point (x, y) lies.
321  *
322  * @param x x point coordinate
323  * @param y y point coordinate
324  * @param edge_size box width/height.
325  */
326 static enum GlyphEdge which_edge(int x, int y, int edge_size)
327 {
328     const int edge_max = edge_size - 1;
329
330     if (!y)
331         return BOTTOM_EDGE;
332     else if (y == edge_max)
333         return TOP_EDGE;
334     else if (!x)
335         return LEFT_EDGE;
336     else if (x == edge_max)
337         return RIGHT_EDGE;
338     else
339         return NO_EDGE;
340 }
341
342 static enum GlyphDir which_direction(enum GlyphEdge edge0, enum GlyphEdge edge1)
343 {
344     if ((edge0 == LEFT_EDGE && edge1 == RIGHT_EDGE) ||
345         (edge1 == LEFT_EDGE && edge0 == RIGHT_EDGE) ||
346         (edge0 == BOTTOM_EDGE && edge1 != TOP_EDGE) ||
347         (edge1 == BOTTOM_EDGE && edge0 != TOP_EDGE))
348         return DIR_UP;
349     else if ((edge0 == TOP_EDGE && edge1 != BOTTOM_EDGE) ||
350              (edge1 == TOP_EDGE && edge0 != BOTTOM_EDGE))
351         return DIR_DOWN;
352     else if ((edge0 == LEFT_EDGE && edge1 != RIGHT_EDGE) ||
353              (edge1 == LEFT_EDGE && edge0 != RIGHT_EDGE))
354         return DIR_LEFT;
355     else if ((edge0 == TOP_EDGE && edge1 == BOTTOM_EDGE) ||
356              (edge1 == TOP_EDGE && edge0 == BOTTOM_EDGE) ||
357              (edge0 == RIGHT_EDGE && edge1 != LEFT_EDGE) ||
358              (edge1 == RIGHT_EDGE && edge0 != LEFT_EDGE))
359         return DIR_RIGHT;
360
361     return NO_DIR;
362 }
363
364 /* Interpolate two points. */
365 static void interp_point(int8_t *points, int x0, int y0, int x1, int y1,
366                          int pos, int npoints)
367 {
368     if (npoints) {
369         points[0] = (x0 * pos + x1 * (npoints - pos) + (npoints >> 1)) / npoints;
370         points[1] = (y0 * pos + y1 * (npoints - pos) + (npoints >> 1)) / npoints;
371     } else {
372         points[0] = x0;
373         points[1] = y0;
374     }
375 }
376
377 /**
378  * Construct glyphs by iterating through vector coordinates.
379  *
380  * @param pglyphs pointer to table where glyphs are stored
381  * @param xvec pointer to x component of vector coordinates
382  * @param yvec pointer to y component of vector coordinates
383  * @param side_length glyph width/height.
384  */
385 static void make_glyphs(int8_t *pglyphs, const int8_t *xvec, const int8_t *yvec,
386                         const int side_length)
387 {
388     const int glyph_size = side_length * side_length;
389     int8_t *pglyph = pglyphs;
390
391     int i, j;
392     for (i = 0; i < GLYPH_COORD_VECT_SIZE; i++) {
393         int x0 = xvec[i];
394         int y0 = yvec[i];
395         enum GlyphEdge edge0 = which_edge(x0, y0, side_length);
396
397         for (j = 0; j < GLYPH_COORD_VECT_SIZE; j++, pglyph += glyph_size) {
398             int x1 = xvec[j];
399             int y1 = yvec[j];
400             enum GlyphEdge edge1 = which_edge(x1, y1, side_length);
401             enum GlyphDir dir = which_direction(edge0, edge1);
402             int npoints = FFMAX(FFABS(x1 - x0), FFABS(y1 - y0));
403             int ipoint;
404
405             for (ipoint = 0; ipoint <= npoints; ipoint++) {
406                 int8_t point[2];
407                 int irow, icol;
408
409                 interp_point(point, x0, y0, x1, y1, ipoint, npoints);
410
411                 switch (dir) {
412                 case DIR_UP:
413                     for (irow = point[1]; irow >= 0; irow--)
414                         pglyph[point[0] + irow * side_length] = 1;
415                     break;
416
417                 case DIR_DOWN:
418                     for (irow = point[1]; irow < side_length; irow++)
419                         pglyph[point[0] + irow * side_length] = 1;
420                     break;
421
422                 case DIR_LEFT:
423                     for (icol = point[0]; icol >= 0; icol--)
424                         pglyph[icol + point[1] * side_length] = 1;
425                     break;
426
427                 case DIR_RIGHT:
428                     for (icol = point[0]; icol < side_length; icol++)
429                         pglyph[icol + point[1] * side_length] = 1;
430                     break;
431                 }
432             }
433         }
434     }
435 }
436
437 static void init_sizes(SANMVideoContext *ctx, int width, int height)
438 {
439     ctx->width   = width;
440     ctx->height  = height;
441     ctx->npixels = width * height;
442
443     ctx->aligned_width  = FFALIGN(width, 8);
444     ctx->aligned_height = FFALIGN(height, 8);
445
446     ctx->buf_size = ctx->aligned_width * ctx->aligned_height * sizeof(ctx->frm0[0]);
447     ctx->pitch    = width;
448 }
449
450 static void destroy_buffers(SANMVideoContext *ctx)
451 {
452     av_freep(&ctx->frm0);
453     av_freep(&ctx->frm1);
454     av_freep(&ctx->frm2);
455     av_freep(&ctx->stored_frame);
456     av_freep(&ctx->rle_buf);
457     ctx->frm0_size =
458     ctx->frm1_size =
459     ctx->frm2_size = 0;
460     init_sizes(ctx, 0, 0);
461 }
462
463 static av_cold int init_buffers(SANMVideoContext *ctx)
464 {
465     av_fast_padded_malloc(&ctx->frm0, &ctx->frm0_size, ctx->buf_size);
466     av_fast_padded_malloc(&ctx->frm1, &ctx->frm1_size, ctx->buf_size);
467     av_fast_padded_malloc(&ctx->frm2, &ctx->frm2_size, ctx->buf_size);
468     if (!ctx->version)
469         av_fast_padded_malloc(&ctx->stored_frame,
470                               &ctx->stored_frame_size, ctx->buf_size);
471
472     if (!ctx->frm0 || !ctx->frm1 || !ctx->frm2 ||
473         (!ctx->stored_frame && !ctx->version)) {
474         destroy_buffers(ctx);
475         return AVERROR(ENOMEM);
476     }
477
478     return 0;
479 }
480
481 static void rotate_bufs(SANMVideoContext *ctx, int rotate_code)
482 {
483     if (rotate_code == 2)
484         FFSWAP(uint16_t*, ctx->frm1, ctx->frm2);
485     FFSWAP(uint16_t*, ctx->frm2, ctx->frm0);
486 }
487
488 static av_cold int decode_init(AVCodecContext *avctx)
489 {
490     SANMVideoContext *ctx = avctx->priv_data;
491
492     ctx->avctx   = avctx;
493     ctx->version = !avctx->extradata_size;
494
495     avctx->pix_fmt = ctx->version ? AV_PIX_FMT_RGB565 : AV_PIX_FMT_PAL8;
496
497     init_sizes(ctx, avctx->width, avctx->height);
498     if (init_buffers(ctx)) {
499         av_log(avctx, AV_LOG_ERROR, "Error allocating buffers.\n");
500         return AVERROR(ENOMEM);
501     }
502
503     make_glyphs(ctx->p4x4glyphs[0], glyph4_x, glyph4_y, 4);
504     make_glyphs(ctx->p8x8glyphs[0], glyph8_x, glyph8_y, 8);
505
506     if (!ctx->version) {
507         int i;
508
509         if (avctx->extradata_size < 1026) {
510             av_log(avctx, AV_LOG_ERROR, "Not enough extradata.\n");
511             return AVERROR_INVALIDDATA;
512         }
513
514         ctx->subversion = AV_RL16(avctx->extradata);
515         for (i = 0; i < PALETTE_SIZE; i++)
516             ctx->pal[i] = 0xFFU << 24 | AV_RL32(avctx->extradata + 2 + i * 4);
517     }
518
519     return 0;
520 }
521
522 static av_cold int decode_end(AVCodecContext *avctx)
523 {
524     SANMVideoContext *ctx = avctx->priv_data;
525
526     destroy_buffers(ctx);
527
528     return 0;
529 }
530
531 static int rle_decode(SANMVideoContext *ctx, uint8_t *dst, const int out_size)
532 {
533     int opcode, color, run_len, left = out_size;
534
535     while (left > 0) {
536         opcode = bytestream2_get_byte(&ctx->gb);
537         run_len = (opcode >> 1) + 1;
538         if (run_len > left || bytestream2_get_bytes_left(&ctx->gb) <= 0)
539             return AVERROR_INVALIDDATA;
540
541         if (opcode & 1) {
542             color = bytestream2_get_byte(&ctx->gb);
543             memset(dst, color, run_len);
544         } else {
545             if (bytestream2_get_bytes_left(&ctx->gb) < run_len)
546                 return AVERROR_INVALIDDATA;
547             bytestream2_get_bufferu(&ctx->gb, dst, run_len);
548         }
549
550         dst  += run_len;
551         left -= run_len;
552     }
553
554     return 0;
555 }
556
557 static int old_codec1(SANMVideoContext *ctx, int top,
558                       int left, int width, int height)
559 {
560     uint8_t *dst = ((uint8_t *)ctx->frm0) + left + top * ctx->pitch;
561     int i, j, len, flag, code, val, pos, end;
562
563     for (i = 0; i < height; i++) {
564         pos = 0;
565
566         if (bytestream2_get_bytes_left(&ctx->gb) < 2)
567             return AVERROR_INVALIDDATA;
568
569         len = bytestream2_get_le16u(&ctx->gb);
570         end = bytestream2_tell(&ctx->gb) + len;
571
572         while (bytestream2_tell(&ctx->gb) < end) {
573             if (bytestream2_get_bytes_left(&ctx->gb) < 2)
574                 return AVERROR_INVALIDDATA;
575
576             code = bytestream2_get_byteu(&ctx->gb);
577             flag = code & 1;
578             code = (code >> 1) + 1;
579             if (pos + code > width)
580                 return AVERROR_INVALIDDATA;
581             if (flag) {
582                 val = bytestream2_get_byteu(&ctx->gb);
583                 if (val)
584                     memset(dst + pos, val, code);
585                 pos += code;
586             } else {
587                 if (bytestream2_get_bytes_left(&ctx->gb) < code)
588                     return AVERROR_INVALIDDATA;
589                 for (j = 0; j < code; j++) {
590                     val = bytestream2_get_byteu(&ctx->gb);
591                     if (val)
592                         dst[pos] = val;
593                     pos++;
594                 }
595             }
596         }
597         dst += ctx->pitch;
598     }
599     ctx->rotate_code = 0;
600
601     return 0;
602 }
603
604 static inline void codec37_mv(uint8_t *dst, const uint8_t *src,
605                               int height, int stride, int x, int y)
606 {
607     int pos, i, j;
608
609     pos = x + y * stride;
610     for (j = 0; j < 4; j++) {
611         for (i = 0; i < 4; i++) {
612             if ((pos + i) < 0 || (pos + i) >= height * stride)
613                 dst[i] = 0;
614             else
615                 dst[i] = src[i];
616         }
617         dst += stride;
618         src += stride;
619         pos += stride;
620     }
621 }
622
623 static int old_codec37(SANMVideoContext *ctx, int top,
624                        int left, int width, int height)
625 {
626     int stride = ctx->pitch;
627     int i, j, k, t;
628     uint8_t *dst, *prev;
629     int skip_run = 0;
630     int compr = bytestream2_get_byte(&ctx->gb);
631     int mvoff = bytestream2_get_byte(&ctx->gb);
632     int seq   = bytestream2_get_le16(&ctx->gb);
633     uint32_t decoded_size = bytestream2_get_le32(&ctx->gb);
634     int flags;
635
636     bytestream2_skip(&ctx->gb, 4);
637     flags = bytestream2_get_byte(&ctx->gb);
638     bytestream2_skip(&ctx->gb, 3);
639
640     if (decoded_size > ctx->height * stride - left - top * stride) {
641         decoded_size = ctx->height * stride - left - top * stride;
642         av_log(ctx->avctx, AV_LOG_WARNING, "Decoded size is too large.\n");
643     }
644
645     ctx->rotate_code = 0;
646
647     if (((seq & 1) || !(flags & 1)) && (compr && compr != 2))
648         rotate_bufs(ctx, 1);
649
650     dst  = ((uint8_t*)ctx->frm0) + left + top * stride;
651     prev = ((uint8_t*)ctx->frm2) + left + top * stride;
652
653     if (mvoff > 2) {
654         av_log(ctx->avctx, AV_LOG_ERROR, "Invalid motion base value %d.\n", mvoff);
655         return AVERROR_INVALIDDATA;
656     }
657
658     switch (compr) {
659     case 0:
660         for (i = 0; i < height; i++) {
661             bytestream2_get_buffer(&ctx->gb, dst, width);
662             dst += stride;
663         }
664         memset(ctx->frm1, 0, ctx->height * stride);
665         memset(ctx->frm2, 0, ctx->height * stride);
666         break;
667     case 2:
668         if (rle_decode(ctx, dst, decoded_size))
669             return AVERROR_INVALIDDATA;
670         memset(ctx->frm1, 0, ctx->frm1_size);
671         memset(ctx->frm2, 0, ctx->frm2_size);
672         break;
673     case 3:
674     case 4:
675         if (flags & 4) {
676             for (j = 0; j < height; j += 4) {
677                 for (i = 0; i < width; i += 4) {
678                     int code;
679                     if (skip_run) {
680                         skip_run--;
681                         copy_block4(dst + i, prev + i, stride, stride, 4);
682                         continue;
683                     }
684                     if (bytestream2_get_bytes_left(&ctx->gb) < 1)
685                         return AVERROR_INVALIDDATA;
686                     code = bytestream2_get_byteu(&ctx->gb);
687                     switch (code) {
688                     case 0xFF:
689                         if (bytestream2_get_bytes_left(&ctx->gb) < 16)
690                             return AVERROR_INVALIDDATA;
691                         for (k = 0; k < 4; k++)
692                             bytestream2_get_bufferu(&ctx->gb, dst + i + k * stride, 4);
693                         break;
694                     case 0xFE:
695                         if (bytestream2_get_bytes_left(&ctx->gb) < 4)
696                             return AVERROR_INVALIDDATA;
697                         for (k = 0; k < 4; k++)
698                             memset(dst + i + k * stride, bytestream2_get_byteu(&ctx->gb), 4);
699                         break;
700                     case 0xFD:
701                         if (bytestream2_get_bytes_left(&ctx->gb) < 1)
702                             return AVERROR_INVALIDDATA;
703                         t = bytestream2_get_byteu(&ctx->gb);
704                         for (k = 0; k < 4; k++)
705                             memset(dst + i + k * stride, t, 4);
706                         break;
707                     default:
708                         if (compr == 4 && !code) {
709                             if (bytestream2_get_bytes_left(&ctx->gb) < 1)
710                                 return AVERROR_INVALIDDATA;
711                             skip_run = bytestream2_get_byteu(&ctx->gb) + 1;
712                             i -= 4;
713                         } else {
714                             int mx, my;
715
716                             mx = c37_mv[(mvoff * 255 + code) * 2];
717                             my = c37_mv[(mvoff * 255 + code) * 2 + 1];
718                             codec37_mv(dst + i, prev + i + mx + my * stride,
719                                        ctx->height, stride, i + mx, j + my);
720                         }
721                     }
722                 }
723                 dst  += stride * 4;
724                 prev += stride * 4;
725             }
726         } else {
727             for (j = 0; j < height; j += 4) {
728                 for (i = 0; i < width; i += 4) {
729                     int code;
730                     if (skip_run) {
731                         skip_run--;
732                         copy_block4(dst + i, prev + i, stride, stride, 4);
733                         continue;
734                     }
735                     code = bytestream2_get_byte(&ctx->gb);
736                     if (code == 0xFF) {
737                         if (bytestream2_get_bytes_left(&ctx->gb) < 16)
738                             return AVERROR_INVALIDDATA;
739                         for (k = 0; k < 4; k++)
740                             bytestream2_get_bufferu(&ctx->gb, dst + i + k * stride, 4);
741                     } else if (compr == 4 && !code) {
742                         if (bytestream2_get_bytes_left(&ctx->gb) < 1)
743                             return AVERROR_INVALIDDATA;
744                         skip_run = bytestream2_get_byteu(&ctx->gb) + 1;
745                         i -= 4;
746                     } else {
747                         int mx, my;
748
749                         mx = c37_mv[(mvoff * 255 + code) * 2];
750                         my = c37_mv[(mvoff * 255 + code) * 2 + 1];
751                         codec37_mv(dst + i, prev + i + mx + my * stride,
752                                    ctx->height, stride, i + mx, j + my);
753                     }
754                 }
755                 dst  += stride * 4;
756                 prev += stride * 4;
757             }
758         }
759         break;
760     default:
761         avpriv_report_missing_feature(ctx->avctx,
762                                       "Subcodec 37 compression %d", compr);
763         return AVERROR_PATCHWELCOME;
764     }
765
766     return 0;
767 }
768
769 static int process_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *prev1,
770                          uint8_t *prev2, int stride, int tbl, int size)
771 {
772     int code, k, t;
773     uint8_t colors[2];
774     int8_t *pglyph;
775
776     if (bytestream2_get_bytes_left(&ctx->gb) < 1)
777         return AVERROR_INVALIDDATA;
778
779     code = bytestream2_get_byteu(&ctx->gb);
780     if (code >= 0xF8) {
781         switch (code) {
782         case 0xFF:
783             if (size == 2) {
784                 if (bytestream2_get_bytes_left(&ctx->gb) < 4)
785                     return AVERROR_INVALIDDATA;
786                 dst[0]          = bytestream2_get_byteu(&ctx->gb);
787                 dst[1]          = bytestream2_get_byteu(&ctx->gb);
788                 dst[0 + stride] = bytestream2_get_byteu(&ctx->gb);
789                 dst[1 + stride] = bytestream2_get_byteu(&ctx->gb);
790             } else {
791                 size >>= 1;
792                 if (process_block(ctx, dst, prev1, prev2, stride, tbl, size))
793                     return AVERROR_INVALIDDATA;
794                 if (process_block(ctx, dst + size, prev1 + size, prev2 + size,
795                                   stride, tbl, size))
796                     return AVERROR_INVALIDDATA;
797                 dst   += size * stride;
798                 prev1 += size * stride;
799                 prev2 += size * stride;
800                 if (process_block(ctx, dst, prev1, prev2, stride, tbl, size))
801                     return AVERROR_INVALIDDATA;
802                 if (process_block(ctx, dst + size, prev1 + size, prev2 + size,
803                                   stride, tbl, size))
804                     return AVERROR_INVALIDDATA;
805             }
806             break;
807         case 0xFE:
808             if (bytestream2_get_bytes_left(&ctx->gb) < 1)
809                 return AVERROR_INVALIDDATA;
810
811             t = bytestream2_get_byteu(&ctx->gb);
812             for (k = 0; k < size; k++)
813                 memset(dst + k * stride, t, size);
814             break;
815         case 0xFD:
816             if (bytestream2_get_bytes_left(&ctx->gb) < 3)
817                 return AVERROR_INVALIDDATA;
818
819             code = bytestream2_get_byteu(&ctx->gb);
820             pglyph = (size == 8) ? ctx->p8x8glyphs[code] : ctx->p4x4glyphs[code];
821             bytestream2_get_bufferu(&ctx->gb, colors, 2);
822
823             for (k = 0; k < size; k++)
824                 for (t = 0; t < size; t++)
825                     dst[t + k * stride] = colors[!*pglyph++];
826             break;
827         case 0xFC:
828             for (k = 0; k < size; k++)
829                 memcpy(dst + k * stride, prev1 + k * stride, size);
830             break;
831         default:
832             k = bytestream2_tell(&ctx->gb);
833             bytestream2_seek(&ctx->gb, tbl + (code & 7), SEEK_SET);
834             t = bytestream2_get_byte(&ctx->gb);
835             bytestream2_seek(&ctx->gb, k, SEEK_SET);
836             for (k = 0; k < size; k++)
837                 memset(dst + k * stride, t, size);
838         }
839     } else {
840         int mx = motion_vectors[code][0];
841         int my = motion_vectors[code][1];
842         int index = prev2 - (const uint8_t *)ctx->frm2;
843
844         av_assert2(index >= 0 && index < (ctx->buf_size >> 1));
845
846         if (index < -mx - my * stride ||
847             (ctx->buf_size >> 1) - index < mx + size + (my + size - 1) * stride) {
848             av_log(ctx->avctx, AV_LOG_ERROR, "MV is invalid.\n");
849             return AVERROR_INVALIDDATA;
850         }
851
852         for (k = 0; k < size; k++)
853             memcpy(dst + k * stride, prev2 + mx + (my + k) * stride, size);
854     }
855
856     return 0;
857 }
858
859 static int old_codec47(SANMVideoContext *ctx, int top,
860                        int left, int width, int height)
861 {
862     uint32_t decoded_size;
863     int i, j;
864     int stride     = ctx->pitch;
865     uint8_t *dst   = (uint8_t *)ctx->frm0 + left + top * stride;
866     uint8_t *prev1 = (uint8_t *)ctx->frm1;
867     uint8_t *prev2 = (uint8_t *)ctx->frm2;
868     int tbl_pos = bytestream2_tell(&ctx->gb);
869     int seq     = bytestream2_get_le16(&ctx->gb);
870     int compr   = bytestream2_get_byte(&ctx->gb);
871     int new_rot = bytestream2_get_byte(&ctx->gb);
872     int skip    = bytestream2_get_byte(&ctx->gb);
873
874     bytestream2_skip(&ctx->gb, 9);
875     decoded_size = bytestream2_get_le32(&ctx->gb);
876     bytestream2_skip(&ctx->gb, 8);
877
878     if (decoded_size > ctx->height * stride - left - top * stride) {
879         decoded_size = ctx->height * stride - left - top * stride;
880         av_log(ctx->avctx, AV_LOG_WARNING, "Decoded size is too large.\n");
881     }
882
883     if (skip & 1)
884         bytestream2_skip(&ctx->gb, 0x8080);
885     if (!seq) {
886         ctx->prev_seq = -1;
887         memset(prev1, 0, ctx->height * stride);
888         memset(prev2, 0, ctx->height * stride);
889     }
890
891     switch (compr) {
892     case 0:
893         if (bytestream2_get_bytes_left(&ctx->gb) < width * height)
894             return AVERROR_INVALIDDATA;
895         for (j = 0; j < height; j++) {
896             bytestream2_get_bufferu(&ctx->gb, dst, width);
897             dst += stride;
898         }
899         break;
900     case 1:
901         if (bytestream2_get_bytes_left(&ctx->gb) < ((width + 1) >> 1) * ((height + 1) >> 1))
902             return AVERROR_INVALIDDATA;
903         for (j = 0; j < height; j += 2) {
904             for (i = 0; i < width; i += 2) {
905                 dst[i] =
906                 dst[i + 1] =
907                 dst[stride + i] =
908                 dst[stride + i + 1] = bytestream2_get_byteu(&ctx->gb);
909             }
910             dst += stride * 2;
911         }
912         break;
913     case 2:
914         if (seq == ctx->prev_seq + 1) {
915             for (j = 0; j < height; j += 8) {
916                 for (i = 0; i < width; i += 8)
917                     if (process_block(ctx, dst + i, prev1 + i, prev2 + i, stride,
918                                       tbl_pos + 8, 8))
919                         return AVERROR_INVALIDDATA;
920                 dst   += stride * 8;
921                 prev1 += stride * 8;
922                 prev2 += stride * 8;
923             }
924         }
925         break;
926     case 3:
927         memcpy(ctx->frm0, ctx->frm2, ctx->pitch * ctx->height);
928         break;
929     case 4:
930         memcpy(ctx->frm0, ctx->frm1, ctx->pitch * ctx->height);
931         break;
932     case 5:
933         if (rle_decode(ctx, dst, decoded_size))
934             return AVERROR_INVALIDDATA;
935         break;
936     default:
937         avpriv_report_missing_feature(ctx->avctx,
938                                       "Subcodec 47 compression %d", compr);
939         return AVERROR_PATCHWELCOME;
940     }
941     if (seq == ctx->prev_seq + 1)
942         ctx->rotate_code = new_rot;
943     else
944         ctx->rotate_code = 0;
945     ctx->prev_seq = seq;
946
947     return 0;
948 }
949
950 static int process_frame_obj(SANMVideoContext *ctx)
951 {
952     uint16_t codec = bytestream2_get_le16u(&ctx->gb);
953     uint16_t left  = bytestream2_get_le16u(&ctx->gb);
954     uint16_t top   = bytestream2_get_le16u(&ctx->gb);
955     uint16_t w     = bytestream2_get_le16u(&ctx->gb);
956     uint16_t h     = bytestream2_get_le16u(&ctx->gb);
957
958     if (!w || !h) {
959         av_log(ctx->avctx, AV_LOG_ERROR, "Dimensions are invalid.\n");
960         return AVERROR_INVALIDDATA;
961     }
962
963     if (ctx->width < left + w || ctx->height < top + h) {
964         int ret = ff_set_dimensions(ctx->avctx, FFMAX(left + w, ctx->width),
965                                     FFMAX(top + h, ctx->height));
966         if (ret < 0)
967             return ret;
968         init_sizes(ctx, FFMAX(left + w, ctx->width),
969                    FFMAX(top + h, ctx->height));
970         if (init_buffers(ctx)) {
971             av_log(ctx->avctx, AV_LOG_ERROR, "Error resizing buffers.\n");
972             return AVERROR(ENOMEM);
973         }
974     }
975     bytestream2_skip(&ctx->gb, 4);
976
977     switch (codec) {
978     case 1:
979     case 3:
980         return old_codec1(ctx, top, left, w, h);
981         break;
982     case 37:
983         return old_codec37(ctx, top, left, w, h);
984         break;
985     case 47:
986         return old_codec47(ctx, top, left, w, h);
987         break;
988     default:
989         avpriv_request_sample(ctx->avctx, "Subcodec %d", codec);
990         return AVERROR_PATCHWELCOME;
991     }
992 }
993
994 static int decode_0(SANMVideoContext *ctx)
995 {
996     uint16_t *frm = ctx->frm0;
997     int x, y;
998
999     if (bytestream2_get_bytes_left(&ctx->gb) < ctx->width * ctx->height * 2) {
1000         av_log(ctx->avctx, AV_LOG_ERROR, "Insufficient data for raw frame.\n");
1001         return AVERROR_INVALIDDATA;
1002     }
1003     for (y = 0; y < ctx->height; y++) {
1004         for (x = 0; x < ctx->width; x++)
1005             frm[x] = bytestream2_get_le16u(&ctx->gb);
1006         frm += ctx->pitch;
1007     }
1008     return 0;
1009 }
1010
1011 static int decode_nop(SANMVideoContext *ctx)
1012 {
1013     avpriv_request_sample(ctx->avctx, "Unknown/unsupported compression type");
1014     return AVERROR_PATCHWELCOME;
1015 }
1016
1017 static void copy_block(uint16_t *pdest, uint16_t *psrc, int block_size, int pitch)
1018 {
1019     uint8_t *dst = (uint8_t *)pdest;
1020     uint8_t *src = (uint8_t *)psrc;
1021     int stride = pitch * 2;
1022
1023     switch (block_size) {
1024     case 2:
1025         copy_block4(dst, src, stride, stride, 2);
1026         break;
1027     case 4:
1028         copy_block8(dst, src, stride, stride, 4);
1029         break;
1030     case 8:
1031         copy_block16(dst, src, stride, stride, 8);
1032         break;
1033     }
1034 }
1035
1036 static void fill_block(uint16_t *pdest, uint16_t color, int block_size, int pitch)
1037 {
1038     int x, y;
1039
1040     pitch -= block_size;
1041     for (y = 0; y < block_size; y++, pdest += pitch)
1042         for (x = 0; x < block_size; x++)
1043             *pdest++ = color;
1044 }
1045
1046 static int draw_glyph(SANMVideoContext *ctx, uint16_t *dst, int index,
1047                       uint16_t fg_color, uint16_t bg_color, int block_size,
1048                       int pitch)
1049 {
1050     int8_t *pglyph;
1051     uint16_t colors[2] = { fg_color, bg_color };
1052     int x, y;
1053
1054     if (index >= NGLYPHS) {
1055         av_log(ctx->avctx, AV_LOG_ERROR, "Ignoring nonexistent glyph #%u.\n", index);
1056         return AVERROR_INVALIDDATA;
1057     }
1058
1059     pglyph = block_size == 8 ? ctx->p8x8glyphs[index] : ctx->p4x4glyphs[index];
1060     pitch -= block_size;
1061
1062     for (y = 0; y < block_size; y++, dst += pitch)
1063         for (x = 0; x < block_size; x++)
1064             *dst++ = colors[*pglyph++];
1065     return 0;
1066 }
1067
1068 static int opcode_0xf7(SANMVideoContext *ctx, int cx, int cy, int block_size, int pitch)
1069 {
1070     uint16_t *dst = ctx->frm0 + cx + cy * ctx->pitch;
1071
1072     if (block_size == 2) {
1073         uint32_t indices;
1074
1075         if (bytestream2_get_bytes_left(&ctx->gb) < 4)
1076             return AVERROR_INVALIDDATA;
1077
1078         indices        = bytestream2_get_le32u(&ctx->gb);
1079         dst[0]         = ctx->codebook[indices & 0xFF];
1080         indices      >>= 8;
1081         dst[1]         = ctx->codebook[indices & 0xFF];
1082         indices      >>= 8;
1083         dst[pitch]     = ctx->codebook[indices & 0xFF];
1084         indices      >>= 8;
1085         dst[pitch + 1] = ctx->codebook[indices & 0xFF];
1086     } else {
1087         uint16_t fgcolor, bgcolor;
1088         int glyph;
1089
1090         if (bytestream2_get_bytes_left(&ctx->gb) < 3)
1091             return AVERROR_INVALIDDATA;
1092
1093         glyph   = bytestream2_get_byteu(&ctx->gb);
1094         bgcolor = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
1095         fgcolor = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
1096
1097         draw_glyph(ctx, dst, glyph, fgcolor, bgcolor, block_size, pitch);
1098     }
1099     return 0;
1100 }
1101
1102 static int opcode_0xf8(SANMVideoContext *ctx, int cx, int cy, int block_size, int pitch)
1103 {
1104     uint16_t *dst = ctx->frm0 + cx + cy * ctx->pitch;
1105
1106     if (block_size == 2) {
1107         if (bytestream2_get_bytes_left(&ctx->gb) < 8)
1108             return AVERROR_INVALIDDATA;
1109
1110         dst[0]         = bytestream2_get_le16u(&ctx->gb);
1111         dst[1]         = bytestream2_get_le16u(&ctx->gb);
1112         dst[pitch]     = bytestream2_get_le16u(&ctx->gb);
1113         dst[pitch + 1] = bytestream2_get_le16u(&ctx->gb);
1114     } else {
1115         uint16_t fgcolor, bgcolor;
1116         int glyph;
1117
1118         if (bytestream2_get_bytes_left(&ctx->gb) < 5)
1119             return AVERROR_INVALIDDATA;
1120
1121         glyph   = bytestream2_get_byteu(&ctx->gb);
1122         bgcolor = bytestream2_get_le16u(&ctx->gb);
1123         fgcolor = bytestream2_get_le16u(&ctx->gb);
1124
1125         draw_glyph(ctx, dst, glyph, fgcolor, bgcolor, block_size, pitch);
1126     }
1127     return 0;
1128 }
1129
1130 static int good_mvec(SANMVideoContext *ctx, int cx, int cy, int mx, int my,
1131                      int block_size)
1132 {
1133     int start_pos = cx + mx + (cy + my) * ctx->pitch;
1134     int end_pos = start_pos + (block_size - 1) * (ctx->pitch + 1);
1135
1136     int good = start_pos >= 0 && end_pos < (ctx->buf_size >> 1);
1137
1138     if (!good)
1139         av_log(ctx->avctx, AV_LOG_ERROR,
1140                "Ignoring invalid motion vector (%i, %i)->(%u, %u), block size = %u\n",
1141                cx + mx, cy + my, cx, cy, block_size);
1142
1143     return good;
1144 }
1145
1146 static int codec2subblock(SANMVideoContext *ctx, int cx, int cy, int blk_size)
1147 {
1148     int16_t mx, my, index;
1149     int opcode;
1150
1151     if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1152         return AVERROR_INVALIDDATA;
1153
1154     opcode = bytestream2_get_byteu(&ctx->gb);
1155
1156     switch (opcode) {
1157     default:
1158         mx = motion_vectors[opcode][0];
1159         my = motion_vectors[opcode][1];
1160
1161         if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
1162             copy_block(ctx->frm0 + cx      + ctx->pitch *  cy,
1163                        ctx->frm2 + cx + mx + ctx->pitch * (cy + my),
1164                        blk_size, ctx->pitch);
1165         }
1166         break;
1167     case 0xF5:
1168         if (bytestream2_get_bytes_left(&ctx->gb) < 2)
1169             return AVERROR_INVALIDDATA;
1170         index = bytestream2_get_le16u(&ctx->gb);
1171
1172         mx = index % ctx->width;
1173         my = index / ctx->width;
1174
1175         if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
1176             copy_block(ctx->frm0 + cx      + ctx->pitch *  cy,
1177                        ctx->frm2 + cx + mx + ctx->pitch * (cy + my),
1178                        blk_size, ctx->pitch);
1179         }
1180         break;
1181     case 0xF6:
1182         copy_block(ctx->frm0 + cx + ctx->pitch * cy,
1183                    ctx->frm1 + cx + ctx->pitch * cy,
1184                    blk_size, ctx->pitch);
1185         break;
1186     case 0xF7:
1187         opcode_0xf7(ctx, cx, cy, blk_size, ctx->pitch);
1188         break;
1189
1190     case 0xF8:
1191         opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch);
1192         break;
1193     case 0xF9:
1194     case 0xFA:
1195     case 0xFB:
1196     case 0xFC:
1197         fill_block(ctx->frm0 + cx + cy * ctx->pitch,
1198                    ctx->small_codebook[opcode - 0xf9], blk_size, ctx->pitch);
1199         break;
1200     case 0xFD:
1201         if (bytestream2_get_bytes_left(&ctx->gb) < 1)
1202             return AVERROR_INVALIDDATA;
1203         fill_block(ctx->frm0 + cx + cy * ctx->pitch,
1204                    ctx->codebook[bytestream2_get_byteu(&ctx->gb)], blk_size, ctx->pitch);
1205         break;
1206     case 0xFE:
1207         if (bytestream2_get_bytes_left(&ctx->gb) < 2)
1208             return AVERROR_INVALIDDATA;
1209         fill_block(ctx->frm0 + cx + cy * ctx->pitch,
1210                    bytestream2_get_le16u(&ctx->gb), blk_size, ctx->pitch);
1211         break;
1212     case 0xFF:
1213         if (blk_size == 2) {
1214             opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch);
1215         } else {
1216             blk_size >>= 1;
1217             if (codec2subblock(ctx, cx, cy, blk_size))
1218                 return AVERROR_INVALIDDATA;
1219             if (codec2subblock(ctx, cx + blk_size, cy, blk_size))
1220                 return AVERROR_INVALIDDATA;
1221             if (codec2subblock(ctx, cx, cy + blk_size, blk_size))
1222                 return AVERROR_INVALIDDATA;
1223             if (codec2subblock(ctx, cx + blk_size, cy + blk_size, blk_size))
1224                 return AVERROR_INVALIDDATA;
1225         }
1226         break;
1227     }
1228     return 0;
1229 }
1230
1231 static int decode_2(SANMVideoContext *ctx)
1232 {
1233     int cx, cy, ret;
1234
1235     for (cy = 0; cy < ctx->aligned_height; cy += 8)
1236         for (cx = 0; cx < ctx->aligned_width; cx += 8)
1237             if (ret = codec2subblock(ctx, cx, cy, 8))
1238                 return ret;
1239
1240     return 0;
1241 }
1242
1243 static int decode_3(SANMVideoContext *ctx)
1244 {
1245     memcpy(ctx->frm0, ctx->frm2, ctx->frm2_size);
1246     return 0;
1247 }
1248
1249 static int decode_4(SANMVideoContext *ctx)
1250 {
1251     memcpy(ctx->frm0, ctx->frm1, ctx->frm1_size);
1252     return 0;
1253 }
1254
1255 static int decode_5(SANMVideoContext *ctx)
1256 {
1257 #if HAVE_BIGENDIAN
1258     uint16_t *frm;
1259     int npixels;
1260 #endif
1261     uint8_t *dst = (uint8_t*)ctx->frm0;
1262
1263     if (rle_decode(ctx, dst, ctx->buf_size))
1264         return AVERROR_INVALIDDATA;
1265
1266 #if HAVE_BIGENDIAN
1267     npixels = ctx->npixels;
1268     frm = ctx->frm0;
1269     while (npixels--) {
1270         *frm = av_bswap16(*frm);
1271         frm++;
1272     }
1273 #endif
1274
1275     return 0;
1276 }
1277
1278 static int decode_6(SANMVideoContext *ctx)
1279 {
1280     int npixels = ctx->npixels;
1281     uint16_t *frm = ctx->frm0;
1282
1283     if (bytestream2_get_bytes_left(&ctx->gb) < npixels) {
1284         av_log(ctx->avctx, AV_LOG_ERROR, "Insufficient data for frame.\n");
1285         return AVERROR_INVALIDDATA;
1286     }
1287     while (npixels--)
1288         *frm++ = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
1289
1290     return 0;
1291 }
1292
1293 static int decode_8(SANMVideoContext *ctx)
1294 {
1295     uint16_t *pdest = ctx->frm0;
1296     uint8_t *rsrc;
1297     long npixels = ctx->npixels;
1298
1299     av_fast_malloc(&ctx->rle_buf, &ctx->rle_buf_size, npixels);
1300     if (!ctx->rle_buf) {
1301         av_log(ctx->avctx, AV_LOG_ERROR, "RLE buffer allocation failed.\n");
1302         return AVERROR(ENOMEM);
1303     }
1304     rsrc = ctx->rle_buf;
1305
1306     if (rle_decode(ctx, rsrc, npixels))
1307         return AVERROR_INVALIDDATA;
1308
1309     while (npixels--)
1310         *pdest++ = ctx->codebook[*rsrc++];
1311
1312     return 0;
1313 }
1314
1315 typedef int (*frm_decoder)(SANMVideoContext *ctx);
1316
1317 static const frm_decoder v1_decoders[] = {
1318     decode_0, decode_nop, decode_2, decode_3, decode_4, decode_5,
1319     decode_6, decode_nop, decode_8
1320 };
1321
1322 static int read_frame_header(SANMVideoContext *ctx, SANMFrameHeader *hdr)
1323 {
1324     int i, ret;
1325
1326     if ((ret = bytestream2_get_bytes_left(&ctx->gb)) < 560) {
1327         av_log(ctx->avctx, AV_LOG_ERROR, "Input frame too short (%d bytes).\n",
1328                ret);
1329         return AVERROR_INVALIDDATA;
1330     }
1331     bytestream2_skip(&ctx->gb, 8); // skip pad
1332
1333     hdr->width  = bytestream2_get_le32u(&ctx->gb);
1334     hdr->height = bytestream2_get_le32u(&ctx->gb);
1335
1336     if (hdr->width != ctx->width || hdr->height != ctx->height) {
1337         avpriv_report_missing_feature(ctx->avctx, "Variable size frames");
1338         return AVERROR_PATCHWELCOME;
1339     }
1340
1341     hdr->seq_num     = bytestream2_get_le16u(&ctx->gb);
1342     hdr->codec       = bytestream2_get_byteu(&ctx->gb);
1343     hdr->rotate_code = bytestream2_get_byteu(&ctx->gb);
1344
1345     bytestream2_skip(&ctx->gb, 4); // skip pad
1346
1347     for (i = 0; i < 4; i++)
1348         ctx->small_codebook[i] = bytestream2_get_le16u(&ctx->gb);
1349     hdr->bg_color = bytestream2_get_le16u(&ctx->gb);
1350
1351     bytestream2_skip(&ctx->gb, 2); // skip pad
1352
1353     hdr->rle_output_size = bytestream2_get_le32u(&ctx->gb);
1354     for (i = 0; i < 256; i++)
1355         ctx->codebook[i] = bytestream2_get_le16u(&ctx->gb);
1356
1357     bytestream2_skip(&ctx->gb, 8); // skip pad
1358
1359     return 0;
1360 }
1361
1362 static void fill_frame(uint16_t *pbuf, int buf_size, uint16_t color)
1363 {
1364     while (buf_size--)
1365         *pbuf++ = color;
1366 }
1367
1368 static int copy_output(SANMVideoContext *ctx, SANMFrameHeader *hdr)
1369 {
1370     uint8_t *dst;
1371     const uint8_t *src = (uint8_t*) ctx->frm0;
1372     int ret, dstpitch, height = ctx->height;
1373     int srcpitch = ctx->pitch * (hdr ? sizeof(ctx->frm0[0]) : 1);
1374
1375     if ((ret = ff_get_buffer(ctx->avctx, ctx->frame, 0)) < 0)
1376         return ret;
1377
1378     dst      = ctx->frame->data[0];
1379     dstpitch = ctx->frame->linesize[0];
1380
1381     while (height--) {
1382         memcpy(dst, src, srcpitch);
1383         src += srcpitch;
1384         dst += dstpitch;
1385     }
1386
1387     return 0;
1388 }
1389
1390 static int decode_frame(AVCodecContext *avctx, void *data,
1391                         int *got_frame_ptr, AVPacket *pkt)
1392 {
1393     SANMVideoContext *ctx = avctx->priv_data;
1394     int i, ret;
1395
1396     ctx->frame = data;
1397     bytestream2_init(&ctx->gb, pkt->data, pkt->size);
1398
1399     if (!ctx->version) {
1400         int to_store = 0;
1401
1402         while (bytestream2_get_bytes_left(&ctx->gb) >= 8) {
1403             uint32_t sig, size;
1404             int pos;
1405
1406             sig  = bytestream2_get_be32u(&ctx->gb);
1407             size = bytestream2_get_be32u(&ctx->gb);
1408             pos  = bytestream2_tell(&ctx->gb);
1409
1410             if (bytestream2_get_bytes_left(&ctx->gb) < size) {
1411                 av_log(avctx, AV_LOG_ERROR, "Incorrect chunk size %"PRIu32".\n", size);
1412                 break;
1413             }
1414             switch (sig) {
1415             case MKBETAG('N', 'P', 'A', 'L'):
1416                 if (size != PALETTE_SIZE * 3) {
1417                     av_log(avctx, AV_LOG_ERROR,
1418                            "Incorrect palette block size %"PRIu32".\n", size);
1419                     return AVERROR_INVALIDDATA;
1420                 }
1421                 for (i = 0; i < PALETTE_SIZE; i++)
1422                     ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb);
1423                 break;
1424             case MKBETAG('F', 'O', 'B', 'J'):
1425                 if (size < 16)
1426                     return AVERROR_INVALIDDATA;
1427                 if (ret = process_frame_obj(ctx))
1428                     return ret;
1429                 break;
1430             case MKBETAG('X', 'P', 'A', 'L'):
1431                 if (size == 6 || size == 4) {
1432                     uint8_t tmp[3];
1433                     int j;
1434
1435                     for (i = 0; i < PALETTE_SIZE; i++) {
1436                         for (j = 0; j < 3; j++) {
1437                             int t = (ctx->pal[i] >> (16 - j * 8)) & 0xFF;
1438                             tmp[j] = av_clip_uint8((t * 129 + ctx->delta_pal[i * 3 + j]) >> 7);
1439                         }
1440                         ctx->pal[i] = 0xFFU << 24 | AV_RB24(tmp);
1441                     }
1442                 } else {
1443                     if (size < PALETTE_DELTA * 2 + 4) {
1444                         av_log(avctx, AV_LOG_ERROR,
1445                                "Incorrect palette change block size %"PRIu32".\n",
1446                                size);
1447                         return AVERROR_INVALIDDATA;
1448                     }
1449                     bytestream2_skipu(&ctx->gb, 4);
1450                     for (i = 0; i < PALETTE_DELTA; i++)
1451                         ctx->delta_pal[i] = bytestream2_get_le16u(&ctx->gb);
1452                     if (size >= PALETTE_DELTA * 5 + 4) {
1453                         for (i = 0; i < PALETTE_SIZE; i++)
1454                             ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb);
1455                     } else {
1456                         memset(ctx->pal, 0, sizeof(ctx->pal));
1457                     }
1458                 }
1459                 break;
1460             case MKBETAG('S', 'T', 'O', 'R'):
1461                 to_store = 1;
1462                 break;
1463             case MKBETAG('F', 'T', 'C', 'H'):
1464                 memcpy(ctx->frm0, ctx->stored_frame, ctx->buf_size);
1465                 break;
1466             default:
1467                 bytestream2_skip(&ctx->gb, size);
1468                 av_log(avctx, AV_LOG_DEBUG,
1469                        "Unknown/unsupported chunk %"PRIx32".\n", sig);
1470                 break;
1471             }
1472
1473             bytestream2_seek(&ctx->gb, pos + size, SEEK_SET);
1474             if (size & 1)
1475                 bytestream2_skip(&ctx->gb, 1);
1476         }
1477         if (to_store)
1478             memcpy(ctx->stored_frame, ctx->frm0, ctx->buf_size);
1479         if ((ret = copy_output(ctx, NULL)))
1480             return ret;
1481         memcpy(ctx->frame->data[1], ctx->pal, 1024);
1482     } else {
1483         SANMFrameHeader header;
1484
1485         if ((ret = read_frame_header(ctx, &header)))
1486             return ret;
1487
1488         ctx->rotate_code = header.rotate_code;
1489         if ((ctx->frame->key_frame = !header.seq_num)) {
1490             ctx->frame->pict_type = AV_PICTURE_TYPE_I;
1491             fill_frame(ctx->frm1, ctx->npixels, header.bg_color);
1492             fill_frame(ctx->frm2, ctx->npixels, header.bg_color);
1493         } else {
1494             ctx->frame->pict_type = AV_PICTURE_TYPE_P;
1495         }
1496
1497         if (header.codec < FF_ARRAY_ELEMS(v1_decoders)) {
1498             if ((ret = v1_decoders[header.codec](ctx))) {
1499                 av_log(avctx, AV_LOG_ERROR,
1500                        "Subcodec %d: error decoding frame.\n", header.codec);
1501                 return ret;
1502             }
1503         } else {
1504             avpriv_request_sample(avctx, "Subcodec %d", header.codec);
1505             return AVERROR_PATCHWELCOME;
1506         }
1507
1508         if ((ret = copy_output(ctx, &header)))
1509             return ret;
1510     }
1511     if (ctx->rotate_code)
1512         rotate_bufs(ctx, ctx->rotate_code);
1513
1514     *got_frame_ptr = 1;
1515
1516     return pkt->size;
1517 }
1518
1519 AVCodec ff_sanm_decoder = {
1520     .name           = "sanm",
1521     .long_name      = NULL_IF_CONFIG_SMALL("LucasArts SANM/Smush video"),
1522     .type           = AVMEDIA_TYPE_VIDEO,
1523     .id             = AV_CODEC_ID_SANM,
1524     .priv_data_size = sizeof(SANMVideoContext),
1525     .init           = decode_init,
1526     .close          = decode_end,
1527     .decode         = decode_frame,
1528     .capabilities   = AV_CODEC_CAP_DR1,
1529 };