Coverage Report

Created: 2026-01-16 07:48

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