2 * MobiClip Video decoder
3 * Copyright (c) 2017 Adib Surani
4 * Copyright (c) 2020 Paul B Mahol
6 * This file is part of FFmpeg.
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.
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.
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
25 #include "libavutil/avassert.h"
26 #include "libavutil/thread.h"
29 #include "bytestream.h"
35 #define MOBI_RL_VLC_BITS 12
36 #define MOBI_MV_VLC_BITS 6
38 static const uint8_t zigzag4x4_tab[] =
40 0x00, 0x04, 0x01, 0x02, 0x05, 0x08, 0x0C, 0x09, 0x06, 0x03, 0x07, 0x0A,
41 0x0D, 0x0E, 0x0B, 0x0F
44 static const uint8_t quant4x4_tab[][16] =
46 { 10, 13, 13, 10, 16, 10, 13, 13, 13, 13, 16, 10, 16, 13, 13, 16 },
47 { 11, 14, 14, 11, 18, 11, 14, 14, 14, 14, 18, 11, 18, 14, 14, 18 },
48 { 13, 16, 16, 13, 20, 13, 16, 16, 16, 16, 20, 13, 20, 16, 16, 20 },
49 { 14, 18, 18, 14, 23, 14, 18, 18, 18, 18, 23, 14, 23, 18, 18, 23 },
50 { 16, 20, 20, 16, 25, 16, 20, 20, 20, 20, 25, 16, 25, 20, 20, 25 },
51 { 18, 23, 23, 18, 29, 18, 23, 23, 23, 23, 29, 18, 29, 23, 23, 29 },
54 static const uint8_t quant8x8_tab[][64] =
56 { 20, 19, 19, 25, 18, 25, 19, 24, 24, 19, 20, 18, 32, 18, 20, 19, 19, 24, 24, 19, 19, 25, 18, 25, 18, 25, 18, 25, 19, 24, 24, 19,
57 19, 24, 24, 19, 18, 32, 18, 20, 18, 32, 18, 24, 24, 19, 19, 24, 24, 18, 25, 18, 25, 18, 19, 24, 24, 19, 18, 32, 18, 24, 24, 18,},
58 { 22, 21, 21, 28, 19, 28, 21, 26, 26, 21, 22, 19, 35, 19, 22, 21, 21, 26, 26, 21, 21, 28, 19, 28, 19, 28, 19, 28, 21, 26, 26, 21,
59 21, 26, 26, 21, 19, 35, 19, 22, 19, 35, 19, 26, 26, 21, 21, 26, 26, 19, 28, 19, 28, 19, 21, 26, 26, 21, 19, 35, 19, 26, 26, 19,},
60 { 26, 24, 24, 33, 23, 33, 24, 31, 31, 24, 26, 23, 42, 23, 26, 24, 24, 31, 31, 24, 24, 33, 23, 33, 23, 33, 23, 33, 24, 31, 31, 24,
61 24, 31, 31, 24, 23, 42, 23, 26, 23, 42, 23, 31, 31, 24, 24, 31, 31, 23, 33, 23, 33, 23, 24, 31, 31, 24, 23, 42, 23, 31, 31, 23,},
62 { 28, 26, 26, 35, 25, 35, 26, 33, 33, 26, 28, 25, 45, 25, 28, 26, 26, 33, 33, 26, 26, 35, 25, 35, 25, 35, 25, 35, 26, 33, 33, 26,
63 26, 33, 33, 26, 25, 45, 25, 28, 25, 45, 25, 33, 33, 26, 26, 33, 33, 25, 35, 25, 35, 25, 26, 33, 33, 26, 25, 45, 25, 33, 33, 25,},
64 { 32, 30, 30, 40, 28, 40, 30, 38, 38, 30, 32, 28, 51, 28, 32, 30, 30, 38, 38, 30, 30, 40, 28, 40, 28, 40, 28, 40, 30, 38, 38, 30,
65 30, 38, 38, 30, 28, 51, 28, 32, 28, 51, 28, 38, 38, 30, 30, 38, 38, 28, 40, 28, 40, 28, 30, 38, 38, 30, 28, 51, 28, 38, 38, 28,},
66 { 36, 34, 34, 46, 32, 46, 34, 43, 43, 34, 36, 32, 58, 32, 36, 34, 34, 43, 43, 34, 34, 46, 32, 46, 32, 46, 32, 46, 34, 43, 43, 34,
67 34, 43, 43, 34, 32, 58, 32, 36, 32, 58, 32, 43, 43, 34, 34, 43, 43, 32, 46, 32, 46, 32, 34, 43, 43, 34, 32, 58, 32, 43, 43, 32,},
70 static const uint8_t block4x4_coefficients_tab[] =
72 15, 0, 2, 1, 4, 8, 12, 3, 11, 13, 14, 7, 10, 5, 9, 6,
75 static const uint8_t pframe_block4x4_coefficients_tab[] =
77 0, 4, 1, 8, 2, 12, 3, 5, 10, 15, 7, 13, 14, 11, 9, 6,
80 static const uint8_t block8x8_coefficients_tab[] =
82 0x00, 0x1F, 0x3F, 0x0F, 0x08, 0x04, 0x02, 0x01, 0x0B, 0x0E, 0x1B, 0x0D,
83 0x03, 0x07, 0x0C, 0x17, 0x1D, 0x0A, 0x1E, 0x05, 0x10, 0x2F, 0x37, 0x3B,
84 0x13, 0x3D, 0x3E, 0x09, 0x1C, 0x06, 0x15, 0x1A, 0x33, 0x11, 0x12, 0x14,
85 0x18, 0x20, 0x3C, 0x35, 0x19, 0x16, 0x3A, 0x30, 0x31, 0x32, 0x27, 0x34,
86 0x2B, 0x2D, 0x39, 0x38, 0x23, 0x36, 0x2E, 0x21, 0x25, 0x22, 0x24, 0x2C,
87 0x2A, 0x28, 0x29, 0x26,
90 static const uint8_t pframe_block8x8_coefficients_tab[] =
92 0x00, 0x0F, 0x04, 0x01, 0x08, 0x02, 0x0C, 0x03, 0x05, 0x0A, 0x0D, 0x07, 0x0E, 0x0B, 0x1F, 0x09,
93 0x06, 0x10, 0x3F, 0x1E, 0x17, 0x1D, 0x1B, 0x1C, 0x13, 0x18, 0x1A, 0x12, 0x11, 0x14, 0x15, 0x20,
94 0x2F, 0x16, 0x19, 0x37, 0x3D, 0x3E, 0x3B, 0x3C, 0x33, 0x35, 0x21, 0x24, 0x22, 0x28, 0x23, 0x2C,
95 0x30, 0x27, 0x2D, 0x25, 0x3A, 0x2B, 0x2E, 0x2A, 0x31, 0x34, 0x38, 0x32, 0x29, 0x26, 0x39, 0x36
98 static const uint8_t run_residue[2][256] =
101 12, 6, 4, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
102 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
103 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
104 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
105 1, 27, 11, 7, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
106 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
107 1, 41, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
108 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
111 27, 10, 5, 4, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
113 8, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
114 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
115 1, 15, 10, 8, 4, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
116 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
117 1, 21, 7, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
118 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
122 static const uint8_t bits0[] = {
123 9, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
124 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12,
125 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 10, 10, 9,
126 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
127 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
128 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6,
129 6, 6, 6, 6, 6, 6, 5, 5, 5, 4, 2, 3, 4, 4,
132 static const uint16_t syms0[] = {
133 0x0, 0x822, 0x803, 0xB, 0xA, 0xB81, 0xB61, 0xB41, 0xB21, 0x122,
134 0x102, 0xE2, 0xC2, 0xA2, 0x63, 0x43, 0x24, 0xC, 0x25, 0x2E1, 0x301,
135 0xBA1, 0xBC1, 0xBE1, 0xC01, 0x26, 0x44, 0x83, 0xA3, 0xC3, 0x142,
136 0x321, 0x341, 0xC21, 0xC41, 0xC61, 0xC81, 0xCA1, 0xCC1, 0xCE1, 0xD01,
137 0x0, 0x9, 0x8, 0xB01, 0xAE1, 0xAC1, 0xAA1, 0xA81, 0xA61, 0xA41, 0xA21,
138 0x802, 0x2C1, 0x2A1, 0x281, 0x261, 0x241, 0x221, 0x201, 0x1E1, 0x82,
139 0x62, 0x7, 0x6, 0xA01, 0x9E1, 0x9C1, 0x9A1, 0x981, 0x961, 0x941, 0x921,
140 0x1C1, 0x1A1, 0x42, 0x23, 0x5, 0x901, 0x8E1, 0x8C1, 0x8A1, 0x181, 0x161,
141 0x141, 0x4, 0x881, 0x861, 0x841, 0x821, 0x121, 0x101, 0xE1, 0xC1, 0x22,
142 0x3, 0xA1, 0x81, 0x61, 0x801, 0x1, 0x21, 0x41, 0x2,
145 static const uint16_t syms1[] = {
146 0x0, 0x807, 0x806, 0x16, 0x15, 0x842, 0x823, 0x805, 0x1A1, 0xA3, 0x102, 0x83,
147 0x64, 0x44, 0x27, 0x14, 0x13, 0x17, 0x18, 0x28, 0x122, 0x862, 0x882, 0x9E1, 0xA01,
148 0x19, 0x1A, 0x1B, 0x29, 0xC3, 0x2A, 0x45, 0xE3, 0x1C1, 0x808, 0x8A2, 0x8C2, 0xA21,
149 0xA41, 0xA61, 0xA81, 0x0, 0x12, 0x11, 0x9C1, 0x9A1, 0x981, 0x961, 0x941, 0x822, 0x804,
150 0x181, 0x161, 0xE2, 0xC2, 0xA2, 0x63, 0x43, 0x26, 0x25, 0x10, 0x82, 0xF, 0xE, 0xD, 0x901,
151 0x8E1, 0x8C1, 0x803, 0x141, 0x121, 0x101, 0x921, 0x62, 0x24, 0xC, 0xB, 0xA, 0x881, 0x861,
152 0xC1, 0x8A1, 0xE1, 0x42, 0x23, 0x9, 0x802, 0xA1, 0x841, 0x821, 0x81, 0x61, 0x8, 0x7, 0x22,
153 0x6, 0x41, 0x5, 0x4, 0x801, 0x1, 0x2, 0x21, 0x3,
156 static const uint8_t mv_len[16] =
158 10, 8, 8, 7, 8, 8, 8, 7, 8, 8, 8, 7, 7, 7, 7, 6,
161 static const uint8_t mv_bits[2][16][10] =
164 { 2, 3, 3, 5, 5, 4, 4, 5, 5, 2 },
165 { 2, 3, 4, 4, 3, 4, 4, 2 },
166 { 3, 4, 4, 2, 4, 4, 3, 2 },
167 { 1, 3, 4, 5, 5, 3, 3 },
168 { 2, 4, 4, 3, 3, 4, 4, 2 },
169 { 2, 3, 4, 4, 4, 4, 3, 2 },
170 { 2, 3, 4, 4, 4, 4, 3, 2 },
171 { 2, 2, 3, 4, 5, 5, 2 },
172 { 2, 3, 4, 4, 3, 4, 4, 2 },
173 { 2, 4, 4, 3, 4, 4, 3, 2 },
174 { 2, 3, 3, 5, 5, 4, 3, 2 },
175 { 2, 3, 4, 4, 3, 3, 2 },
176 { 1, 4, 4, 3, 3, 4, 4 },
177 { 2, 3, 4, 4, 3, 3, 2 },
178 { 2, 3, 4, 4, 3, 3, 2 },
179 { 3, 3, 2, 2, 3, 3 },
182 { 3, 4, 5, 5, 3, 5, 6, 6, 4, 1 },
183 { 2, 3, 4, 5, 5, 2, 3, 3 },
184 { 2, 4, 4, 3, 3, 4, 4, 2 },
185 { 1, 4, 4, 3, 4, 4, 3 },
186 { 3, 3, 2, 4, 5, 5, 3, 2 },
187 { 3, 4, 4, 3, 3, 3, 3, 2 },
188 { 1, 3, 3, 4, 4, 4, 5, 5 },
189 { 1, 4, 4, 3, 3, 4, 4 },
190 { 2, 4, 4, 3, 3, 4, 4, 2 },
191 { 1, 3, 3, 4, 4, 4, 5, 5 },
192 { 2, 3, 4, 4, 4, 4, 3, 2 },
193 { 2, 3, 3, 4, 4, 3, 2 },
194 { 1, 4, 4, 3, 3, 4, 4 },
195 { 1, 4, 4, 3, 3, 4, 4 },
196 { 2, 3, 3, 4, 4, 3, 2 },
197 { 2, 3, 3, 3, 3, 2 },
201 static const uint8_t mv_syms[2][16][10] =
204 { 1, 8, 9, 4, 3, 2, 7, 5, 6, 0 },
205 { 0, 9, 5, 4, 2, 3, 8, 1 },
206 { 3, 9, 5, 0, 4, 8, 2, 1 },
207 { 1, 3, 4, 8, 5, 2, 0 },
208 { 0, 5, 4, 8, 2, 3, 9, 1 },
209 { 0, 3, 5, 9, 4, 8, 2, 1 },
210 { 0, 3, 9, 5, 8, 4, 2, 1 },
211 { 0, 2, 3, 4, 8, 5, 1 },
212 { 0, 3, 8, 4, 2, 5, 9, 1 },
213 { 2, 8, 9, 3, 5, 4, 0, 1 },
214 { 0, 4, 3, 8, 9, 5, 2, 1 },
215 { 0, 4, 8, 5, 3, 2, 1 },
216 { 1, 9, 4, 2, 0, 5, 3 },
217 { 2, 4, 9, 5, 3, 0, 1 },
218 { 0, 4, 9, 5, 3, 2, 1 },
219 { 5, 4, 1, 0, 3, 2 },
222 { 8, 2, 3, 6, 1, 7, 5, 4, 9, 0 },
223 { 9, 2, 3, 5, 4, 1, 8, 0 },
224 { 0, 5, 4, 2, 9, 3, 8, 1 },
225 { 1, 5, 4, 2, 8, 3, 0 },
226 { 2, 9, 8, 3, 5, 4, 0, 1 },
227 { 3, 5, 4, 2, 9, 8, 0, 1 },
228 { 1, 2, 0, 9, 8, 3, 5, 4 },
229 { 1, 8, 5, 2, 0, 4, 3 },
230 { 0, 5, 4, 2, 8, 3, 9, 1 },
231 { 1, 2, 0, 9, 8, 3, 5, 4 },
232 { 0, 3, 9, 8, 5, 4, 2, 1 },
233 { 0, 4, 3, 8, 5, 2, 1 },
234 { 1, 5, 4, 2, 0, 9, 3 },
235 { 1, 9, 5, 2, 0, 4, 3 },
236 { 0, 5, 3, 9, 4, 2, 1 },
237 { 0, 4, 5, 3, 2, 1 },
241 typedef struct BlockXY {
250 typedef struct MotionXY {
254 typedef struct MobiClipContext {
272 BswapDSPContext bdsp;
275 static VLC rl_vlc[2];
276 static VLC mv_vlc[2][16];
278 static av_cold void mobiclip_init_static(void)
280 INIT_VLC_STATIC_FROM_LENGTHS(&rl_vlc[0], MOBI_RL_VLC_BITS, 104,
281 bits0, sizeof(*bits0),
282 syms0, sizeof(*syms0), sizeof(*syms0),
283 0, 0, 1 << MOBI_RL_VLC_BITS);
284 INIT_VLC_STATIC_FROM_LENGTHS(&rl_vlc[1], MOBI_RL_VLC_BITS, 104,
285 bits0, sizeof(*bits0),
286 syms1, sizeof(*syms1), sizeof(*syms1),
287 0, 0, 1 << MOBI_RL_VLC_BITS);
288 for (int i = 0; i < 2; i++) {
289 static VLC_TYPE vlc_buf[2 * 16 << MOBI_MV_VLC_BITS][2];
290 for (int j = 0; j < 16; j++) {
291 mv_vlc[i][j].table = &vlc_buf[(16 * i + j) << MOBI_MV_VLC_BITS];
292 mv_vlc[i][j].table_allocated = 1 << MOBI_MV_VLC_BITS;
293 ff_init_vlc_from_lengths(&mv_vlc[i][j], MOBI_MV_VLC_BITS, mv_len[j],
294 mv_bits[i][j], sizeof(*mv_bits[i][j]),
295 mv_syms[i][j], sizeof(*mv_syms[i][j]), sizeof(*mv_syms[i][j]),
296 0, INIT_VLC_USE_NEW_STATIC, NULL);
301 static av_cold int mobiclip_init(AVCodecContext *avctx)
303 static AVOnce init_static_once = AV_ONCE_INIT;
304 MobiClipContext *s = avctx->priv_data;
306 if (avctx->width & 15 || avctx->height & 15) {
307 av_log(avctx, AV_LOG_ERROR, "width/height not multiple of 16\n");
308 return AVERROR_INVALIDDATA;
311 ff_bswapdsp_init(&s->bdsp);
313 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
315 s->motion = av_calloc(avctx->width / 16 + 3, sizeof(MotionXY));
317 return AVERROR(ENOMEM);
318 s->motion_size = (avctx->width / 16 + 3) * sizeof(MotionXY);
320 for (int i = 0; i < 6; i++) {
321 s->pic[i] = av_frame_alloc();
323 return AVERROR(ENOMEM);
326 ff_thread_once(&init_static_once, mobiclip_init_static);
331 static int setup_qtables(AVCodecContext *avctx, int quantizer)
333 MobiClipContext *s = avctx->priv_data;
336 if (quantizer < 12 || quantizer > 161)
337 return AVERROR_INVALIDDATA;
339 s->quantizer = quantizer;
344 for (int i = 0; i < 16; i++)
345 s->qtab[0][i] = quant4x4_tab[qx][i] << qy;
347 for (int i = 0; i < 64; i++)
348 s->qtab[1][i] = quant8x8_tab[qx][i] << (qy - 2);
350 for (int i = 0; i < 20; i++)
356 static void inverse4(unsigned *rs)
358 unsigned a = rs[0] + rs[2];
359 unsigned b = rs[0] - rs[2];
360 unsigned c = rs[1] + ((int)rs[3] >> 1);
361 unsigned d = ((int)rs[1] >> 1) - rs[3];
369 static void idct(int *arr, int size)
372 unsigned x3, x2, x1, x0;
387 e = (unsigned)arr[7] + arr[1] - arr[3] - (arr[3] >> 1);
388 f = (unsigned)arr[7] - arr[1] + arr[5] + (arr[5] >> 1);
389 g = (unsigned)arr[5] - arr[3] - arr[7] - (arr[7] >> 1);
390 h = (unsigned)arr[5] + arr[3] + arr[1] + (arr[1] >> 1);
391 x3 = (unsigned)g + (h >> 2);
392 x2 = (unsigned)e + (f >> 2);
393 x1 = (e >> 2) - (unsigned)f;
394 x0 = (unsigned)h - (g >> 2);
396 arr[0] = tmp[0] + x0;
397 arr[1] = tmp[1] + x1;
398 arr[2] = tmp[2] + x2;
399 arr[3] = tmp[3] + x3;
400 arr[4] = tmp[3] - x3;
401 arr[5] = tmp[2] - x2;
402 arr[6] = tmp[1] - x1;
403 arr[7] = tmp[0] - x0;
406 static void read_run_encoding(AVCodecContext *avctx,
407 int *last, int *run, int *level)
409 MobiClipContext *s = avctx->priv_data;
410 GetBitContext *gb = &s->gb;
411 int n = get_vlc2(gb, rl_vlc[s->dct_tab_idx].table,
412 MOBI_RL_VLC_BITS, 1);
414 *last = (n >> 11) == 1;
415 *run = (n >> 5) & 0x3F;
419 static int add_coefficients(AVCodecContext *avctx, AVFrame *frame,
420 int bx, int by, int size, int plane)
422 MobiClipContext *s = avctx->priv_data;
423 GetBitContext *gb = &s->gb;
425 const uint8_t *ztab = size == 8 ? ff_zigzag_direct : zigzag4x4_tab;
426 const int *qtab = s->qtab[size == 8];
427 uint8_t *dst = frame->data[plane] + by * frame->linesize[plane] + bx;
429 for (int pos = 0; get_bits_left(gb) > 0; pos++) {
430 int qval, last, run, level;
432 read_run_encoding(avctx, &last, &run, &level);
437 } else if (!get_bits1(gb)) {
438 read_run_encoding(avctx, &last, &run, &level);
439 level += run_residue[s->dct_tab_idx][(last ? 64 : 0) + run];
442 } else if (!get_bits1(gb)) {
443 read_run_encoding(avctx, &last, &run, &level);
444 run += run_residue[s->dct_tab_idx][128 + (last ? 64 : 0) + level];
448 last = get_bits1(gb);
449 run = get_bits(gb, 6);
450 level = get_sbits(gb, 12);
454 if (pos >= size * size)
455 return AVERROR_INVALIDDATA;
457 mat[ztab[pos]] = qval *(unsigned)level;
464 for (int y = 0; y < size; y++)
465 idct(&mat[y * size], size);
467 for (int y = 0; y < size; y++) {
468 for (int x = y + 1; x < size; x++) {
469 int a = mat[x * size + y];
470 int b = mat[y * size + x];
472 mat[y * size + x] = a;
473 mat[x * size + y] = b;
476 idct(&mat[y * size], size);
477 for (int x = 0; x < size; x++)
478 dst[x] = av_clip_uint8(dst[x] + (mat[y * size + x] >> 6));
479 dst += frame->linesize[plane];
485 static int add_pframe_coefficients(AVCodecContext *avctx, AVFrame *frame,
486 int bx, int by, int size, int plane)
488 MobiClipContext *s = avctx->priv_data;
489 GetBitContext *gb = &s->gb;
490 int ret, idx = get_ue_golomb_31(gb);
493 ret = add_coefficients(avctx, frame, bx, by, size, plane);
494 } else if ((unsigned)idx < FF_ARRAY_ELEMS(pframe_block4x4_coefficients_tab)) {
495 int flags = pframe_block4x4_coefficients_tab[idx];
497 for (int y = by; y < by + 8; y += 4) {
498 for (int x = bx; x < bx + 8; x += 4) {
500 ret = add_coefficients(avctx, frame, x, y, 4, plane);
508 ret = AVERROR_INVALIDDATA;
514 static int adjust(int x, int size)
516 return size == 16 ? (x + 1) >> 1 : x;
519 static uint8_t pget(BlockXY b)
524 if (b.x == -1 && b.y >= b.size) {
525 ret.x = -1, ret.y = b.size - 1;
526 } else if (b.x >= -1 && b.y >= -1) {
527 ret.x = b.x, ret.y = b.y;
528 } else if (b.x == -1 && b.y == -2) {
529 ret.x = 0, ret.y = -1;
530 } else if (b.x == -2 && b.y == -1) {
531 ret.x = -1, ret.y = 0;
534 y = av_clip(ret.ay + ret.y, 0, ret.h - 1);
535 x = av_clip(ret.ax + ret.x, 0, ret.w - 1);
537 return ret.block[y * ret.linesize + x];
540 static uint8_t half(int a, int b)
542 return ((a + b) + 1) / 2;
545 static uint8_t half3(int a, int b, int c)
547 return ((a + b + b + c) * 2 / 4 + 1) / 2;;
550 static uint8_t pick_above(BlockXY bxy)
557 static uint8_t pick_left(BlockXY bxy)
564 static uint8_t half_horz(BlockXY bxy)
566 BlockXY a = bxy, b = bxy, c = bxy;
571 return half3(pget(a), pget(b), pget(c));
574 static uint8_t half_vert(BlockXY bxy)
576 BlockXY a = bxy, b = bxy, c = bxy;
581 return half3(pget(a), pget(b), pget(c));
584 static uint8_t pick_4(BlockXY bxy)
588 if ((bxy.x % 2) == 0) {
594 ba.y = bxy.y + bxy.x / 2;
599 bb.y = bxy.y + bxy.x / 2 + 1;
608 ba.y = bxy.y + bxy.x / 2 + 1;
615 static uint8_t pick_5(BlockXY bxy)
628 val = half(pget(a), pget(b));
629 } else if (bxy.y == 0) {
636 } else if (bxy.x == 1) {
655 static uint8_t pick_6(BlockXY bxy)
668 val = half(pget(a), pget(b));
669 } else if (bxy.x == 0) {
676 } else if (bxy.y == 1) {
695 static uint8_t pick_7(BlockXY bxy)
724 return half3(acc1, clr, acc2);
727 static uint8_t pick_8(BlockXY bxy)
745 } else if (bxy.y == 1) {
750 } else if (bxy.x < bxy.size - 1) {
755 } else if (bxy.y % 2 == 0) {
758 ba.x = bxy.y / 2 + bxy.size - 1;
762 bb.x = bxy.y / 2 + bxy.size;
769 ba.x = bxy.y / 2 + bxy.size;
778 static void block_fill_simple(uint8_t *block, int size, int linesize, int fill)
780 for (int y = 0; y < size; y++) {
781 memset(block, fill, size);
786 static void block_fill(uint8_t *block, int size, int linesize,
787 int w, int h, int ax, int ay,
788 uint8_t (*pick)(BlockXY bxy))
794 bxy.linesize = linesize;
800 for (int y = 0; y < size; y++) {
802 for (int x = 0; x < size; x++) {
809 block[ax + x + (ay + y) * linesize] = val;
814 static int block_sum(const uint8_t *block, int w, int h, int linesize)
818 for (int y = 0; y < h; y++) {
819 for (int x = 0; x < w; x++) {
828 static int predict_intra(AVCodecContext *avctx, AVFrame *frame, int ax, int ay,
829 int pmode, int add_coeffs, int size, int plane)
831 MobiClipContext *s = avctx->priv_data;
832 GetBitContext *gb = &s->gb;
833 int w = avctx->width >> !!plane, h = avctx->height >> !!plane;
838 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_above);
841 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_left);
847 uint8_t *top = frame->data[plane] + FFMAX(ay - 1, 0) * frame->linesize[plane] + ax;
848 uint8_t *left = frame->data[plane] + ay * frame->linesize[plane] + FFMAX(ax - 1, 0);
849 int bottommost = frame->data[plane][(ay + size - 1) * frame->linesize[plane] + FFMAX(ax - 1, 0)];
850 int rightmost = frame->data[plane][FFMAX(ay - 1, 0) * frame->linesize[plane] + ax + size - 1];
851 int avg = (bottommost + rightmost + 1) / 2 + 2 * av_clip(get_se_golomb(gb), -(1<<16), 1<<16);
852 int r6 = adjust(avg - bottommost, size);
853 int r9 = adjust(avg - rightmost, size);
854 int shift = adjust(size, size) == 8 ? 3 : 2;
857 for (int x = 0; x < size; x++) {
859 arr1[x] = adjust(((bottommost - val) * (1 << shift)) + r6 * (x + 1), size);
862 for (int y = 0; y < size; y++) {
863 int val = left[y * frame->linesize[plane]];
864 arr2[y] = adjust(((rightmost - val) * (1 << shift)) + r9 * (y + 1), size);
867 block = frame->data[plane] + ay * frame->linesize[plane] + ax;
868 for (int y = 0; y < size; y++) {
869 for (int x = 0; x < size; x++) {
870 block[x] = (((top[x] + left[0] + ((arr1[x] * (y + 1) +
871 arr2[y] * (x + 1)) >> 2 * shift)) + 1) / 2) & 0xFF;
873 block += frame->linesize[plane];
874 left += frame->linesize[plane];
882 if (ax == 0 && ay == 0) {
884 } else if (ax >= 1 && ay >= 1) {
885 int left = block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1,
886 1, size, frame->linesize[plane]);
887 int top = block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax,
888 size, 1, frame->linesize[plane]);
890 fill = ((left + top) * 2 / (2 * size) + 1) / 2;
891 } else if (ax >= 1) {
892 fill = (block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1,
893 1, size, frame->linesize[plane]) * 2 / size + 1) / 2;
894 } else if (ay >= 1) {
895 fill = (block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax,
896 size, 1, frame->linesize[plane]) * 2 / size + 1) / 2;
901 block_fill_simple(frame->data[plane] + ay * frame->linesize[plane] + ax,
902 size, frame->linesize[plane], fill);
906 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_4);
909 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_5);
912 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_6);
915 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_7);
918 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_8);
923 ret = add_coefficients(avctx, frame, ax, ay, size, plane);
928 static int get_prediction(AVCodecContext *avctx, int x, int y, int size)
930 MobiClipContext *s = avctx->priv_data;
931 GetBitContext *gb = &s->gb;
932 int index = (y & 0xC) | (x / 4 % 4);
934 uint8_t val = FFMIN(s->pre[index], index % 4 == 0 ? 9 : s->pre[index + 3]);
938 if (!get_bits1(gb)) {
939 int x = get_bits(gb, 3);
940 val = x + (x >= val ? 1 : 0);
943 s->pre[index + 4] = val;
945 s->pre[index + 5] = s->pre[index + 8] = s->pre[index + 9] = val;
950 static int process_block(AVCodecContext *avctx, AVFrame *frame,
951 int x, int y, int pmode, int has_coeffs, int plane)
953 MobiClipContext *s = avctx->priv_data;
954 GetBitContext *gb = &s->gb;
959 pmode = get_prediction(avctx, x, y, 8);
960 return predict_intra(avctx, frame, x, y, pmode, 0, 8, plane);
963 tmp = get_ue_golomb_31(gb);
964 if ((unsigned)tmp > FF_ARRAY_ELEMS(block4x4_coefficients_tab))
965 return AVERROR_INVALIDDATA;
969 pmode = get_prediction(avctx, x, y, 8);
970 ret = predict_intra(avctx, frame, x, y, pmode, 1, 8, plane);
972 int flags = block4x4_coefficients_tab[tmp - 1];
974 for (int by = y; by < y + 8; by += 4) {
975 for (int bx = x; bx < x + 8; bx += 4) {
976 int new_pmode = pmode;
979 new_pmode = get_prediction(avctx, bx, by, 4);
980 ret = predict_intra(avctx, frame, bx, by, new_pmode, flags & 1, 4, plane);
991 static int decode_macroblock(AVCodecContext *avctx, AVFrame *frame,
992 int x, int y, int predict)
994 MobiClipContext *s = avctx->priv_data;
995 GetBitContext *gb = &s->gb;
996 int flags, pmode_uv, idx = get_ue_golomb(gb);
999 if (idx < 0 || idx >= FF_ARRAY_ELEMS(block8x8_coefficients_tab))
1000 return AVERROR_INVALIDDATA;
1002 flags = block8x8_coefficients_tab[idx];
1005 ret = process_block(avctx, frame, x, y, -1, flags & 1, 0);
1009 ret = process_block(avctx, frame, x + 8, y, -1, flags & 1, 0);
1013 ret = process_block(avctx, frame, x, y + 8, -1, flags & 1, 0);
1017 ret = process_block(avctx, frame, x + 8, y + 8, -1, flags & 1, 0);
1022 int pmode = get_bits(gb, 3);
1025 ret = predict_intra(avctx, frame, x, y, pmode, 0, 16, 0);
1031 ret = process_block(avctx, frame, x, y, pmode, flags & 1, 0);
1035 ret = process_block(avctx, frame, x + 8, y, pmode, flags & 1, 0);
1039 ret = process_block(avctx, frame, x, y + 8, pmode, flags & 1, 0);
1043 ret = process_block(avctx, frame, x + 8, y + 8, pmode, flags & 1, 0);
1049 pmode_uv = get_bits(gb, 3);
1050 if (pmode_uv == 2) {
1051 ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 1 + !s->moflex);
1054 ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 2 - !s->moflex);
1060 ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 1 + !s->moflex);
1064 ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 2 - !s->moflex);
1071 static int get_index(int x)
1073 return x == 16 ? 0 : x == 8 ? 1 : x == 4 ? 2 : x == 2 ? 3 : 0;
1076 static int predict_motion(AVCodecContext *avctx,
1077 int width, int height, int index,
1078 int offsetm, int offsetx, int offsety)
1080 MobiClipContext *s = avctx->priv_data;
1081 MotionXY *motion = s->motion;
1082 GetBitContext *gb = &s->gb;
1083 int fheight = avctx->height;
1084 int fwidth = avctx->width;
1087 int sidx = -FFMAX(1, index) + s->current_pic;
1088 MotionXY mv = s->motion[0];
1094 mv.x = mv.x + get_se_golomb(gb);
1095 mv.y = mv.y + get_se_golomb(gb);
1097 if (mv.x >= INT_MAX || mv.y >= INT_MAX)
1098 return AVERROR_INVALIDDATA;
1100 motion[offsetm].x = mv.x;
1101 motion[offsetm].y = mv.y;
1103 for (int i = 0; i < 3; i++) {
1104 int method, src_linesize, dst_linesize;
1108 offsetx = offsetx >> 1;
1109 offsety = offsety >> 1;
1113 height = height >> 1;
1114 fwidth = fwidth >> 1;
1115 fheight = fheight >> 1;
1118 av_assert0(s->pic[sidx]);
1119 av_assert0(s->pic[s->current_pic]);
1120 av_assert0(s->pic[s->current_pic]->data[i]);
1121 if (!s->pic[sidx]->data[i])
1122 return AVERROR_INVALIDDATA;
1124 method = (mv.x & 1) | ((mv.y & 1) << 1);
1125 src_linesize = s->pic[sidx]->linesize[i];
1126 dst_linesize = s->pic[s->current_pic]->linesize[i];
1127 dst = s->pic[s->current_pic]->data[i] + offsetx + offsety * dst_linesize;
1129 if (offsetx + (mv.x >> 1) < 0 ||
1130 offsety + (mv.y >> 1) < 0 ||
1131 offsetx + width + (mv.x + 1 >> 1) > fwidth ||
1132 offsety + height + (mv.y + 1 >> 1) > fheight)
1133 return AVERROR_INVALIDDATA;
1137 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1138 (offsety + (mv.y >> 1)) * src_linesize;
1139 for (int y = 0; y < height; y++) {
1140 for (int x = 0; x < width; x++)
1142 dst += dst_linesize;
1143 src += src_linesize;
1147 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1148 (offsety + (mv.y >> 1)) * src_linesize;
1149 for (int y = 0; y < height; y++) {
1150 for (int x = 0; x < width; x++) {
1151 dst[x] = (uint8_t)((src[x] >> 1) + (src[x + 1] >> 1));
1154 dst += dst_linesize;
1155 src += src_linesize;
1159 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1160 (offsety + (mv.y >> 1)) * src_linesize;
1161 for (int y = 0; y < height; y++) {
1162 for (int x = 0; x < width; x++) {
1163 dst[x] = (uint8_t)((src[x] >> 1) + (src[x + src_linesize] >> 1));
1166 dst += dst_linesize;
1167 src += src_linesize;
1171 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1172 (offsety + (mv.y >> 1)) * src_linesize;
1173 for (int y = 0; y < height; y++) {
1174 for (int x = 0; x < width; x++) {
1175 dst[x] = (uint8_t)((((src[x] >> 1) + (src[x + 1] >> 1)) >> 1) +
1176 (((src[x + src_linesize] >> 1) + (src[x + 1 + src_linesize] >> 1)) >> 1));
1179 dst += dst_linesize;
1180 src += src_linesize;
1187 int adjx = index == 8 ? 0 : width / 2;
1188 int adjy = index == 8 ? height / 2 : 0;
1190 width = width - adjx;
1191 height = height - adjy;
1192 tidx = get_index(height) * 4 + get_index(width);
1194 for (int i = 0; i < 2; i++) {
1197 idx2 = get_vlc2(gb, mv_vlc[s->moflex][tidx].table,
1198 MOBI_MV_VLC_BITS, 1);
1200 ret = predict_motion(avctx, width, height, idx2,
1201 offsetm, offsetx + i * adjx, offsety + i * adjy);
1210 static int mobiclip_decode(AVCodecContext *avctx, void *data,
1211 int *got_frame, AVPacket *pkt)
1213 MobiClipContext *s = avctx->priv_data;
1214 GetBitContext *gb = &s->gb;
1215 AVFrame *frame = s->pic[s->current_pic];
1218 av_fast_padded_malloc(&s->bitstream, &s->bitstream_size,
1221 if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0)
1224 s->bdsp.bswap16_buf((uint16_t *)s->bitstream,
1225 (uint16_t *)pkt->data,
1226 (pkt->size + 1) >> 1);
1228 ret = init_get_bits8(gb, s->bitstream, FFALIGN(pkt->size, 2));
1232 if (get_bits1(gb)) {
1233 frame->pict_type = AV_PICTURE_TYPE_I;
1234 frame->key_frame = 1;
1235 s->moflex = get_bits1(gb);
1236 s->dct_tab_idx = get_bits1(gb);
1238 ret = setup_qtables(avctx, get_bits(gb, 6));
1242 for (int y = 0; y < avctx->height; y += 16) {
1243 for (int x = 0; x < avctx->width; x += 16) {
1244 ret = decode_macroblock(avctx, frame, x, y, get_bits1(gb));
1250 MotionXY *motion = s->motion;
1252 memset(motion, 0, s->motion_size);
1254 frame->pict_type = AV_PICTURE_TYPE_P;
1255 frame->key_frame = 0;
1258 ret = setup_qtables(avctx, s->quantizer + get_se_golomb(gb));
1262 for (int y = 0; y < avctx->height; y += 16) {
1263 for (int x = 0; x < avctx->width; x += 16) {
1266 motion[0].x = mid_pred(motion[x / 16 + 1].x, motion[x / 16 + 2].x, motion[x / 16 + 3].x);
1267 motion[0].y = mid_pred(motion[x / 16 + 1].y, motion[x / 16 + 2].y, motion[x / 16 + 3].y);
1268 motion[x / 16 + 2].x = 0;
1269 motion[x / 16 + 2].y = 0;
1271 idx = get_vlc2(gb, mv_vlc[s->moflex][0].table,
1272 MOBI_MV_VLC_BITS, 1);
1274 if (idx == 6 || idx == 7) {
1275 ret = decode_macroblock(avctx, frame, x, y, idx == 7);
1280 ret = predict_motion(avctx, 16, 16, idx, x / 16 + 2, x, y);
1283 idx2 = get_ue_golomb(gb);
1284 if (idx2 >= FF_ARRAY_ELEMS(pframe_block8x8_coefficients_tab))
1285 return AVERROR_INVALIDDATA;
1286 flags = pframe_block8x8_coefficients_tab[idx2];
1288 for (int sy = y; sy < y + 16; sy += 8) {
1289 for (int sx = x; sx < x + 16; sx += 8) {
1291 add_pframe_coefficients(avctx, frame, sx, sy, 8, 0);
1297 add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 1 + !s->moflex);
1300 add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 2 - !s->moflex);
1307 avctx->colorspace = AVCOL_SPC_YCGCO;
1309 s->current_pic = (s->current_pic + 1) % 6;
1310 ret = av_frame_ref(data, frame);
1318 static void mobiclip_flush(AVCodecContext *avctx)
1320 MobiClipContext *s = avctx->priv_data;
1322 for (int i = 0; i < 6; i++)
1323 av_frame_unref(s->pic[i]);
1326 static av_cold int mobiclip_close(AVCodecContext *avctx)
1328 MobiClipContext *s = avctx->priv_data;
1330 av_freep(&s->bitstream);
1331 s->bitstream_size = 0;
1332 av_freep(&s->motion);
1335 for (int i = 0; i < 6; i++) {
1336 av_frame_free(&s->pic[i]);
1342 AVCodec ff_mobiclip_decoder = {
1344 .long_name = NULL_IF_CONFIG_SMALL("MobiClip Video"),
1345 .type = AVMEDIA_TYPE_VIDEO,
1346 .id = AV_CODEC_ID_MOBICLIP,
1347 .priv_data_size = sizeof(MobiClipContext),
1348 .init = mobiclip_init,
1349 .decode = mobiclip_decode,
1350 .flush = mobiclip_flush,
1351 .close = mobiclip_close,
1352 .capabilities = AV_CODEC_CAP_DR1,
1353 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,