2 * MobiClip Video decoder
3 * Copyright (c) 2015-2016 Florian Nouwt
4 * Copyright (c) 2017 Adib Surani
5 * Copyright (c) 2020 Paul B Mahol
7 * This file is part of FFmpeg.
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "libavutil/avassert.h"
27 #include "libavutil/thread.h"
30 #include "bytestream.h"
36 #define MOBI_RL_VLC_BITS 12
37 #define MOBI_MV_VLC_BITS 6
39 static const uint8_t zigzag4x4_tab[] =
41 0x00, 0x04, 0x01, 0x02, 0x05, 0x08, 0x0C, 0x09, 0x06, 0x03, 0x07, 0x0A,
42 0x0D, 0x0E, 0x0B, 0x0F
45 static const uint8_t quant4x4_tab[][16] =
47 { 10, 13, 13, 10, 16, 10, 13, 13, 13, 13, 16, 10, 16, 13, 13, 16 },
48 { 11, 14, 14, 11, 18, 11, 14, 14, 14, 14, 18, 11, 18, 14, 14, 18 },
49 { 13, 16, 16, 13, 20, 13, 16, 16, 16, 16, 20, 13, 20, 16, 16, 20 },
50 { 14, 18, 18, 14, 23, 14, 18, 18, 18, 18, 23, 14, 23, 18, 18, 23 },
51 { 16, 20, 20, 16, 25, 16, 20, 20, 20, 20, 25, 16, 25, 20, 20, 25 },
52 { 18, 23, 23, 18, 29, 18, 23, 23, 23, 23, 29, 18, 29, 23, 23, 29 },
55 static const uint8_t quant8x8_tab[][64] =
57 { 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,
58 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,},
59 { 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,
60 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,},
61 { 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,
62 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,},
63 { 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,
64 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,},
65 { 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,
66 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,},
67 { 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,
68 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,},
71 static const uint8_t block4x4_coefficients_tab[] =
73 15, 0, 2, 1, 4, 8, 12, 3, 11, 13, 14, 7, 10, 5, 9, 6,
76 static const uint8_t pframe_block4x4_coefficients_tab[] =
78 0, 4, 1, 8, 2, 12, 3, 5, 10, 15, 7, 13, 14, 11, 9, 6,
81 static const uint8_t block8x8_coefficients_tab[] =
83 0x00, 0x1F, 0x3F, 0x0F, 0x08, 0x04, 0x02, 0x01, 0x0B, 0x0E, 0x1B, 0x0D,
84 0x03, 0x07, 0x0C, 0x17, 0x1D, 0x0A, 0x1E, 0x05, 0x10, 0x2F, 0x37, 0x3B,
85 0x13, 0x3D, 0x3E, 0x09, 0x1C, 0x06, 0x15, 0x1A, 0x33, 0x11, 0x12, 0x14,
86 0x18, 0x20, 0x3C, 0x35, 0x19, 0x16, 0x3A, 0x30, 0x31, 0x32, 0x27, 0x34,
87 0x2B, 0x2D, 0x39, 0x38, 0x23, 0x36, 0x2E, 0x21, 0x25, 0x22, 0x24, 0x2C,
88 0x2A, 0x28, 0x29, 0x26,
91 static const uint8_t pframe_block8x8_coefficients_tab[] =
93 0x00, 0x0F, 0x04, 0x01, 0x08, 0x02, 0x0C, 0x03, 0x05, 0x0A, 0x0D, 0x07, 0x0E, 0x0B, 0x1F, 0x09,
94 0x06, 0x10, 0x3F, 0x1E, 0x17, 0x1D, 0x1B, 0x1C, 0x13, 0x18, 0x1A, 0x12, 0x11, 0x14, 0x15, 0x20,
95 0x2F, 0x16, 0x19, 0x37, 0x3D, 0x3E, 0x3B, 0x3C, 0x33, 0x35, 0x21, 0x24, 0x22, 0x28, 0x23, 0x2C,
96 0x30, 0x27, 0x2D, 0x25, 0x3A, 0x2B, 0x2E, 0x2A, 0x31, 0x34, 0x38, 0x32, 0x29, 0x26, 0x39, 0x36
99 static const uint8_t run_residue[2][256] =
102 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,
103 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,
104 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,
105 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,
106 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,
107 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,
108 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,
109 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,
112 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,
113 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,
114 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,
115 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,
116 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,
117 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,
118 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,
119 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,
123 static const uint8_t bits0[] = {
124 9, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
125 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12,
126 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 10, 10, 9,
127 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
128 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
129 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6,
130 6, 6, 6, 6, 6, 6, 5, 5, 5, 4, 2, 3, 4, 4,
133 static const uint16_t syms0[] = {
134 0x0, 0x822, 0x803, 0xB, 0xA, 0xB81, 0xB61, 0xB41, 0xB21, 0x122,
135 0x102, 0xE2, 0xC2, 0xA2, 0x63, 0x43, 0x24, 0xC, 0x25, 0x2E1, 0x301,
136 0xBA1, 0xBC1, 0xBE1, 0xC01, 0x26, 0x44, 0x83, 0xA3, 0xC3, 0x142,
137 0x321, 0x341, 0xC21, 0xC41, 0xC61, 0xC81, 0xCA1, 0xCC1, 0xCE1, 0xD01,
138 0x0, 0x9, 0x8, 0xB01, 0xAE1, 0xAC1, 0xAA1, 0xA81, 0xA61, 0xA41, 0xA21,
139 0x802, 0x2C1, 0x2A1, 0x281, 0x261, 0x241, 0x221, 0x201, 0x1E1, 0x82,
140 0x62, 0x7, 0x6, 0xA01, 0x9E1, 0x9C1, 0x9A1, 0x981, 0x961, 0x941, 0x921,
141 0x1C1, 0x1A1, 0x42, 0x23, 0x5, 0x901, 0x8E1, 0x8C1, 0x8A1, 0x181, 0x161,
142 0x141, 0x4, 0x881, 0x861, 0x841, 0x821, 0x121, 0x101, 0xE1, 0xC1, 0x22,
143 0x3, 0xA1, 0x81, 0x61, 0x801, 0x1, 0x21, 0x41, 0x2,
146 static const uint16_t syms1[] = {
147 0x0, 0x807, 0x806, 0x16, 0x15, 0x842, 0x823, 0x805, 0x1A1, 0xA3, 0x102, 0x83,
148 0x64, 0x44, 0x27, 0x14, 0x13, 0x17, 0x18, 0x28, 0x122, 0x862, 0x882, 0x9E1, 0xA01,
149 0x19, 0x1A, 0x1B, 0x29, 0xC3, 0x2A, 0x45, 0xE3, 0x1C1, 0x808, 0x8A2, 0x8C2, 0xA21,
150 0xA41, 0xA61, 0xA81, 0x0, 0x12, 0x11, 0x9C1, 0x9A1, 0x981, 0x961, 0x941, 0x822, 0x804,
151 0x181, 0x161, 0xE2, 0xC2, 0xA2, 0x63, 0x43, 0x26, 0x25, 0x10, 0x82, 0xF, 0xE, 0xD, 0x901,
152 0x8E1, 0x8C1, 0x803, 0x141, 0x121, 0x101, 0x921, 0x62, 0x24, 0xC, 0xB, 0xA, 0x881, 0x861,
153 0xC1, 0x8A1, 0xE1, 0x42, 0x23, 0x9, 0x802, 0xA1, 0x841, 0x821, 0x81, 0x61, 0x8, 0x7, 0x22,
154 0x6, 0x41, 0x5, 0x4, 0x801, 0x1, 0x2, 0x21, 0x3,
157 static const uint8_t mv_len[16] =
159 10, 8, 8, 7, 8, 8, 8, 7, 8, 8, 8, 7, 7, 7, 7, 6,
162 static const uint8_t mv_bits[2][16][10] =
165 { 2, 3, 3, 5, 5, 4, 4, 5, 5, 2 },
166 { 2, 3, 4, 4, 3, 4, 4, 2 },
167 { 3, 4, 4, 2, 4, 4, 3, 2 },
168 { 1, 3, 4, 5, 5, 3, 3 },
169 { 2, 4, 4, 3, 3, 4, 4, 2 },
170 { 2, 3, 4, 4, 4, 4, 3, 2 },
171 { 2, 3, 4, 4, 4, 4, 3, 2 },
172 { 2, 2, 3, 4, 5, 5, 2 },
173 { 2, 3, 4, 4, 3, 4, 4, 2 },
174 { 2, 4, 4, 3, 4, 4, 3, 2 },
175 { 2, 3, 3, 5, 5, 4, 3, 2 },
176 { 2, 3, 4, 4, 3, 3, 2 },
177 { 1, 4, 4, 3, 3, 4, 4 },
178 { 2, 3, 4, 4, 3, 3, 2 },
179 { 2, 3, 4, 4, 3, 3, 2 },
180 { 3, 3, 2, 2, 3, 3 },
183 { 3, 4, 5, 5, 3, 5, 6, 6, 4, 1 },
184 { 2, 3, 4, 5, 5, 2, 3, 3 },
185 { 2, 4, 4, 3, 3, 4, 4, 2 },
186 { 1, 4, 4, 3, 4, 4, 3 },
187 { 3, 3, 2, 4, 5, 5, 3, 2 },
188 { 3, 4, 4, 3, 3, 3, 3, 2 },
189 { 1, 3, 3, 4, 4, 4, 5, 5 },
190 { 1, 4, 4, 3, 3, 4, 4 },
191 { 2, 4, 4, 3, 3, 4, 4, 2 },
192 { 1, 3, 3, 4, 4, 4, 5, 5 },
193 { 2, 3, 4, 4, 4, 4, 3, 2 },
194 { 2, 3, 3, 4, 4, 3, 2 },
195 { 1, 4, 4, 3, 3, 4, 4 },
196 { 1, 4, 4, 3, 3, 4, 4 },
197 { 2, 3, 3, 4, 4, 3, 2 },
198 { 2, 3, 3, 3, 3, 2 },
202 static const uint8_t mv_syms[2][16][10] =
205 { 1, 8, 9, 4, 3, 2, 7, 5, 6, 0 },
206 { 0, 9, 5, 4, 2, 3, 8, 1 },
207 { 3, 9, 5, 0, 4, 8, 2, 1 },
208 { 1, 3, 4, 8, 5, 2, 0 },
209 { 0, 5, 4, 8, 2, 3, 9, 1 },
210 { 0, 3, 5, 9, 4, 8, 2, 1 },
211 { 0, 3, 9, 5, 8, 4, 2, 1 },
212 { 0, 2, 3, 4, 8, 5, 1 },
213 { 0, 3, 8, 4, 2, 5, 9, 1 },
214 { 2, 8, 9, 3, 5, 4, 0, 1 },
215 { 0, 4, 3, 8, 9, 5, 2, 1 },
216 { 0, 4, 8, 5, 3, 2, 1 },
217 { 1, 9, 4, 2, 0, 5, 3 },
218 { 2, 4, 9, 5, 3, 0, 1 },
219 { 0, 4, 9, 5, 3, 2, 1 },
220 { 5, 4, 1, 0, 3, 2 },
223 { 8, 2, 3, 6, 1, 7, 5, 4, 9, 0 },
224 { 9, 2, 3, 5, 4, 1, 8, 0 },
225 { 0, 5, 4, 2, 9, 3, 8, 1 },
226 { 1, 5, 4, 2, 8, 3, 0 },
227 { 2, 9, 8, 3, 5, 4, 0, 1 },
228 { 3, 5, 4, 2, 9, 8, 0, 1 },
229 { 1, 2, 0, 9, 8, 3, 5, 4 },
230 { 1, 8, 5, 2, 0, 4, 3 },
231 { 0, 5, 4, 2, 8, 3, 9, 1 },
232 { 1, 2, 0, 9, 8, 3, 5, 4 },
233 { 0, 3, 9, 8, 5, 4, 2, 1 },
234 { 0, 4, 3, 8, 5, 2, 1 },
235 { 1, 5, 4, 2, 0, 9, 3 },
236 { 1, 9, 5, 2, 0, 4, 3 },
237 { 0, 5, 3, 9, 4, 2, 1 },
238 { 0, 4, 5, 3, 2, 1 },
242 typedef struct BlockXY {
251 typedef struct MotionXY {
255 typedef struct MobiClipContext {
273 BswapDSPContext bdsp;
276 static VLC rl_vlc[2];
277 static VLC mv_vlc[2][16];
279 static av_cold void mobiclip_init_static(void)
281 INIT_VLC_STATIC_FROM_LENGTHS(&rl_vlc[0], MOBI_RL_VLC_BITS, 104,
282 bits0, sizeof(*bits0),
283 syms0, sizeof(*syms0), sizeof(*syms0),
284 0, 0, 1 << MOBI_RL_VLC_BITS);
285 INIT_VLC_STATIC_FROM_LENGTHS(&rl_vlc[1], MOBI_RL_VLC_BITS, 104,
286 bits0, sizeof(*bits0),
287 syms1, sizeof(*syms1), sizeof(*syms1),
288 0, 0, 1 << MOBI_RL_VLC_BITS);
289 for (int i = 0; i < 2; i++) {
290 static VLC_TYPE vlc_buf[2 * 16 << MOBI_MV_VLC_BITS][2];
291 for (int j = 0; j < 16; j++) {
292 mv_vlc[i][j].table = &vlc_buf[(16 * i + j) << MOBI_MV_VLC_BITS];
293 mv_vlc[i][j].table_allocated = 1 << MOBI_MV_VLC_BITS;
294 ff_init_vlc_from_lengths(&mv_vlc[i][j], MOBI_MV_VLC_BITS, mv_len[j],
295 mv_bits[i][j], sizeof(*mv_bits[i][j]),
296 mv_syms[i][j], sizeof(*mv_syms[i][j]), sizeof(*mv_syms[i][j]),
297 0, INIT_VLC_USE_NEW_STATIC, NULL);
302 static av_cold int mobiclip_init(AVCodecContext *avctx)
304 static AVOnce init_static_once = AV_ONCE_INIT;
305 MobiClipContext *s = avctx->priv_data;
307 if (avctx->width & 15 || avctx->height & 15) {
308 av_log(avctx, AV_LOG_ERROR, "width/height not multiple of 16\n");
309 return AVERROR_INVALIDDATA;
312 ff_bswapdsp_init(&s->bdsp);
314 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
316 s->motion = av_calloc(avctx->width / 16 + 3, sizeof(MotionXY));
318 return AVERROR(ENOMEM);
319 s->motion_size = (avctx->width / 16 + 3) * sizeof(MotionXY);
321 for (int i = 0; i < 6; i++) {
322 s->pic[i] = av_frame_alloc();
324 return AVERROR(ENOMEM);
327 ff_thread_once(&init_static_once, mobiclip_init_static);
332 static int setup_qtables(AVCodecContext *avctx, int quantizer)
334 MobiClipContext *s = avctx->priv_data;
337 if (quantizer < 12 || quantizer > 161)
338 return AVERROR_INVALIDDATA;
340 s->quantizer = quantizer;
345 for (int i = 0; i < 16; i++)
346 s->qtab[0][i] = quant4x4_tab[qx][i] << qy;
348 for (int i = 0; i < 64; i++)
349 s->qtab[1][i] = quant8x8_tab[qx][i] << (qy - 2);
351 for (int i = 0; i < 20; i++)
357 static void inverse4(unsigned *rs)
359 unsigned a = rs[0] + rs[2];
360 unsigned b = rs[0] - rs[2];
361 unsigned c = rs[1] + ((int)rs[3] >> 1);
362 unsigned d = ((int)rs[1] >> 1) - rs[3];
370 static void idct(int *arr, int size)
373 unsigned x3, x2, x1, x0;
388 e = (unsigned)arr[7] + arr[1] - arr[3] - (arr[3] >> 1);
389 f = (unsigned)arr[7] - arr[1] + arr[5] + (arr[5] >> 1);
390 g = (unsigned)arr[5] - arr[3] - arr[7] - (arr[7] >> 1);
391 h = (unsigned)arr[5] + arr[3] + arr[1] + (arr[1] >> 1);
392 x3 = (unsigned)g + (h >> 2);
393 x2 = (unsigned)e + (f >> 2);
394 x1 = (e >> 2) - (unsigned)f;
395 x0 = (unsigned)h - (g >> 2);
397 arr[0] = tmp[0] + x0;
398 arr[1] = tmp[1] + x1;
399 arr[2] = tmp[2] + x2;
400 arr[3] = tmp[3] + x3;
401 arr[4] = tmp[3] - x3;
402 arr[5] = tmp[2] - x2;
403 arr[6] = tmp[1] - x1;
404 arr[7] = tmp[0] - x0;
407 static void read_run_encoding(AVCodecContext *avctx,
408 int *last, int *run, int *level)
410 MobiClipContext *s = avctx->priv_data;
411 GetBitContext *gb = &s->gb;
412 int n = get_vlc2(gb, rl_vlc[s->dct_tab_idx].table,
413 MOBI_RL_VLC_BITS, 1);
415 *last = (n >> 11) == 1;
416 *run = (n >> 5) & 0x3F;
420 static int add_coefficients(AVCodecContext *avctx, AVFrame *frame,
421 int bx, int by, int size, int plane)
423 MobiClipContext *s = avctx->priv_data;
424 GetBitContext *gb = &s->gb;
426 const uint8_t *ztab = size == 8 ? ff_zigzag_direct : zigzag4x4_tab;
427 const int *qtab = s->qtab[size == 8];
428 uint8_t *dst = frame->data[plane] + by * frame->linesize[plane] + bx;
430 for (int pos = 0; get_bits_left(gb) > 0; pos++) {
431 int qval, last, run, level;
433 read_run_encoding(avctx, &last, &run, &level);
438 } else if (!get_bits1(gb)) {
439 read_run_encoding(avctx, &last, &run, &level);
440 level += run_residue[s->dct_tab_idx][(last ? 64 : 0) + run];
443 } else if (!get_bits1(gb)) {
444 read_run_encoding(avctx, &last, &run, &level);
445 run += run_residue[s->dct_tab_idx][128 + (last ? 64 : 0) + level];
449 last = get_bits1(gb);
450 run = get_bits(gb, 6);
451 level = get_sbits(gb, 12);
455 if (pos >= size * size)
456 return AVERROR_INVALIDDATA;
458 mat[ztab[pos]] = qval *(unsigned)level;
465 for (int y = 0; y < size; y++)
466 idct(&mat[y * size], size);
468 for (int y = 0; y < size; y++) {
469 for (int x = y + 1; x < size; x++) {
470 int a = mat[x * size + y];
471 int b = mat[y * size + x];
473 mat[y * size + x] = a;
474 mat[x * size + y] = b;
477 idct(&mat[y * size], size);
478 for (int x = 0; x < size; x++)
479 dst[x] = av_clip_uint8(dst[x] + (mat[y * size + x] >> 6));
480 dst += frame->linesize[plane];
486 static int add_pframe_coefficients(AVCodecContext *avctx, AVFrame *frame,
487 int bx, int by, int size, int plane)
489 MobiClipContext *s = avctx->priv_data;
490 GetBitContext *gb = &s->gb;
491 int ret, idx = get_ue_golomb_31(gb);
494 ret = add_coefficients(avctx, frame, bx, by, size, plane);
495 } else if ((unsigned)idx < FF_ARRAY_ELEMS(pframe_block4x4_coefficients_tab)) {
496 int flags = pframe_block4x4_coefficients_tab[idx];
498 for (int y = by; y < by + 8; y += 4) {
499 for (int x = bx; x < bx + 8; x += 4) {
501 ret = add_coefficients(avctx, frame, x, y, 4, plane);
509 ret = AVERROR_INVALIDDATA;
515 static int adjust(int x, int size)
517 return size == 16 ? (x + 1) >> 1 : x;
520 static uint8_t pget(BlockXY b)
525 if (b.x == -1 && b.y >= b.size) {
526 ret.x = -1, ret.y = b.size - 1;
527 } else if (b.x >= -1 && b.y >= -1) {
528 ret.x = b.x, ret.y = b.y;
529 } else if (b.x == -1 && b.y == -2) {
530 ret.x = 0, ret.y = -1;
531 } else if (b.x == -2 && b.y == -1) {
532 ret.x = -1, ret.y = 0;
535 y = av_clip(ret.ay + ret.y, 0, ret.h - 1);
536 x = av_clip(ret.ax + ret.x, 0, ret.w - 1);
538 return ret.block[y * ret.linesize + x];
541 static uint8_t half(int a, int b)
543 return ((a + b) + 1) / 2;
546 static uint8_t half3(int a, int b, int c)
548 return ((a + b + b + c) * 2 / 4 + 1) / 2;
551 static uint8_t pick_above(BlockXY bxy)
558 static uint8_t pick_left(BlockXY bxy)
565 static uint8_t half_horz(BlockXY bxy)
567 BlockXY a = bxy, b = bxy, c = bxy;
572 return half3(pget(a), pget(b), pget(c));
575 static uint8_t half_vert(BlockXY bxy)
577 BlockXY a = bxy, b = bxy, c = bxy;
582 return half3(pget(a), pget(b), pget(c));
585 static uint8_t pick_4(BlockXY bxy)
589 if ((bxy.x % 2) == 0) {
595 ba.y = bxy.y + bxy.x / 2;
600 bb.y = bxy.y + bxy.x / 2 + 1;
609 ba.y = bxy.y + bxy.x / 2 + 1;
616 static uint8_t pick_5(BlockXY bxy)
629 val = half(pget(a), pget(b));
630 } else if (bxy.y == 0) {
637 } else if (bxy.x == 1) {
656 static uint8_t pick_6(BlockXY bxy)
669 val = half(pget(a), pget(b));
670 } else if (bxy.x == 0) {
677 } else if (bxy.y == 1) {
696 static uint8_t pick_7(BlockXY bxy)
725 return half3(acc1, clr, acc2);
728 static uint8_t pick_8(BlockXY bxy)
746 } else if (bxy.y == 1) {
751 } else if (bxy.x < bxy.size - 1) {
756 } else if (bxy.y % 2 == 0) {
759 ba.x = bxy.y / 2 + bxy.size - 1;
763 bb.x = bxy.y / 2 + bxy.size;
770 ba.x = bxy.y / 2 + bxy.size;
779 static void block_fill_simple(uint8_t *block, int size, int linesize, int fill)
781 for (int y = 0; y < size; y++) {
782 memset(block, fill, size);
787 static void block_fill(uint8_t *block, int size, int linesize,
788 int w, int h, int ax, int ay,
789 uint8_t (*pick)(BlockXY bxy))
795 bxy.linesize = linesize;
801 for (int y = 0; y < size; y++) {
803 for (int x = 0; x < size; x++) {
810 block[ax + x + (ay + y) * linesize] = val;
815 static int block_sum(const uint8_t *block, int w, int h, int linesize)
819 for (int y = 0; y < h; y++) {
820 for (int x = 0; x < w; x++) {
829 static int predict_intra(AVCodecContext *avctx, AVFrame *frame, int ax, int ay,
830 int pmode, int add_coeffs, int size, int plane)
832 MobiClipContext *s = avctx->priv_data;
833 GetBitContext *gb = &s->gb;
834 int w = avctx->width >> !!plane, h = avctx->height >> !!plane;
839 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_above);
842 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_left);
848 uint8_t *top = frame->data[plane] + FFMAX(ay - 1, 0) * frame->linesize[plane] + ax;
849 uint8_t *left = frame->data[plane] + ay * frame->linesize[plane] + FFMAX(ax - 1, 0);
850 int bottommost = frame->data[plane][(ay + size - 1) * frame->linesize[plane] + FFMAX(ax - 1, 0)];
851 int rightmost = frame->data[plane][FFMAX(ay - 1, 0) * frame->linesize[plane] + ax + size - 1];
852 int avg = (bottommost + rightmost + 1) / 2 + 2 * av_clip(get_se_golomb(gb), -(1<<16), 1<<16);
853 int r6 = adjust(avg - bottommost, size);
854 int r9 = adjust(avg - rightmost, size);
855 int shift = adjust(size, size) == 8 ? 3 : 2;
858 for (int x = 0; x < size; x++) {
860 arr1[x] = adjust(((bottommost - val) * (1 << shift)) + r6 * (x + 1), size);
863 for (int y = 0; y < size; y++) {
864 int val = left[y * frame->linesize[plane]];
865 arr2[y] = adjust(((rightmost - val) * (1 << shift)) + r9 * (y + 1), size);
868 block = frame->data[plane] + ay * frame->linesize[plane] + ax;
869 for (int y = 0; y < size; y++) {
870 for (int x = 0; x < size; x++) {
871 block[x] = (((top[x] + left[0] + ((arr1[x] * (y + 1) +
872 arr2[y] * (x + 1)) >> 2 * shift)) + 1) / 2) & 0xFF;
874 block += frame->linesize[plane];
875 left += frame->linesize[plane];
883 if (ax == 0 && ay == 0) {
885 } else if (ax >= 1 && ay >= 1) {
886 int left = block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1,
887 1, size, frame->linesize[plane]);
888 int top = block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax,
889 size, 1, frame->linesize[plane]);
891 fill = ((left + top) * 2 / (2 * size) + 1) / 2;
892 } else if (ax >= 1) {
893 fill = (block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1,
894 1, size, frame->linesize[plane]) * 2 / size + 1) / 2;
895 } else if (ay >= 1) {
896 fill = (block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax,
897 size, 1, frame->linesize[plane]) * 2 / size + 1) / 2;
902 block_fill_simple(frame->data[plane] + ay * frame->linesize[plane] + ax,
903 size, frame->linesize[plane], fill);
907 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_4);
910 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_5);
913 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_6);
916 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_7);
919 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_8);
924 ret = add_coefficients(avctx, frame, ax, ay, size, plane);
929 static int get_prediction(AVCodecContext *avctx, int x, int y, int size)
931 MobiClipContext *s = avctx->priv_data;
932 GetBitContext *gb = &s->gb;
933 int index = (y & 0xC) | (x / 4 % 4);
935 uint8_t val = FFMIN(s->pre[index], index % 4 == 0 ? 9 : s->pre[index + 3]);
939 if (!get_bits1(gb)) {
940 int x = get_bits(gb, 3);
941 val = x + (x >= val ? 1 : 0);
944 s->pre[index + 4] = val;
946 s->pre[index + 5] = s->pre[index + 8] = s->pre[index + 9] = val;
951 static int process_block(AVCodecContext *avctx, AVFrame *frame,
952 int x, int y, int pmode, int has_coeffs, int plane)
954 MobiClipContext *s = avctx->priv_data;
955 GetBitContext *gb = &s->gb;
960 pmode = get_prediction(avctx, x, y, 8);
961 return predict_intra(avctx, frame, x, y, pmode, 0, 8, plane);
964 tmp = get_ue_golomb_31(gb);
965 if ((unsigned)tmp > FF_ARRAY_ELEMS(block4x4_coefficients_tab))
966 return AVERROR_INVALIDDATA;
970 pmode = get_prediction(avctx, x, y, 8);
971 ret = predict_intra(avctx, frame, x, y, pmode, 1, 8, plane);
973 int flags = block4x4_coefficients_tab[tmp - 1];
975 for (int by = y; by < y + 8; by += 4) {
976 for (int bx = x; bx < x + 8; bx += 4) {
977 int new_pmode = pmode;
980 new_pmode = get_prediction(avctx, bx, by, 4);
981 ret = predict_intra(avctx, frame, bx, by, new_pmode, flags & 1, 4, plane);
992 static int decode_macroblock(AVCodecContext *avctx, AVFrame *frame,
993 int x, int y, int predict)
995 MobiClipContext *s = avctx->priv_data;
996 GetBitContext *gb = &s->gb;
997 int flags, pmode_uv, idx = get_ue_golomb(gb);
1000 if (idx < 0 || idx >= FF_ARRAY_ELEMS(block8x8_coefficients_tab))
1001 return AVERROR_INVALIDDATA;
1003 flags = block8x8_coefficients_tab[idx];
1006 ret = process_block(avctx, frame, x, y, -1, flags & 1, 0);
1010 ret = process_block(avctx, frame, x + 8, y, -1, flags & 1, 0);
1014 ret = process_block(avctx, frame, x, y + 8, -1, flags & 1, 0);
1018 ret = process_block(avctx, frame, x + 8, y + 8, -1, flags & 1, 0);
1023 int pmode = get_bits(gb, 3);
1026 ret = predict_intra(avctx, frame, x, y, pmode, 0, 16, 0);
1032 ret = process_block(avctx, frame, x, y, pmode, flags & 1, 0);
1036 ret = process_block(avctx, frame, x + 8, y, pmode, flags & 1, 0);
1040 ret = process_block(avctx, frame, x, y + 8, pmode, flags & 1, 0);
1044 ret = process_block(avctx, frame, x + 8, y + 8, pmode, flags & 1, 0);
1050 pmode_uv = get_bits(gb, 3);
1051 if (pmode_uv == 2) {
1052 ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 1 + !s->moflex);
1055 ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 2 - !s->moflex);
1061 ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 1 + !s->moflex);
1065 ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 2 - !s->moflex);
1072 static int get_index(int x)
1074 return x == 16 ? 0 : x == 8 ? 1 : x == 4 ? 2 : x == 2 ? 3 : 0;
1077 static int predict_motion(AVCodecContext *avctx,
1078 int width, int height, int index,
1079 int offsetm, int offsetx, int offsety)
1081 MobiClipContext *s = avctx->priv_data;
1082 MotionXY *motion = s->motion;
1083 GetBitContext *gb = &s->gb;
1084 int fheight = avctx->height;
1085 int fwidth = avctx->width;
1088 int sidx = -FFMAX(1, index) + s->current_pic;
1089 MotionXY mv = s->motion[0];
1095 mv.x = mv.x + (unsigned)get_se_golomb(gb);
1096 mv.y = mv.y + (unsigned)get_se_golomb(gb);
1098 if (mv.x >= INT_MAX || mv.y >= INT_MAX)
1099 return AVERROR_INVALIDDATA;
1101 motion[offsetm].x = mv.x;
1102 motion[offsetm].y = mv.y;
1104 for (int i = 0; i < 3; i++) {
1105 int method, src_linesize, dst_linesize;
1109 offsetx = offsetx >> 1;
1110 offsety = offsety >> 1;
1114 height = height >> 1;
1115 fwidth = fwidth >> 1;
1116 fheight = fheight >> 1;
1119 av_assert0(s->pic[sidx]);
1120 av_assert0(s->pic[s->current_pic]);
1121 av_assert0(s->pic[s->current_pic]->data[i]);
1122 if (!s->pic[sidx]->data[i])
1123 return AVERROR_INVALIDDATA;
1125 method = (mv.x & 1) | ((mv.y & 1) << 1);
1126 src_linesize = s->pic[sidx]->linesize[i];
1127 dst_linesize = s->pic[s->current_pic]->linesize[i];
1128 dst = s->pic[s->current_pic]->data[i] + offsetx + offsety * dst_linesize;
1130 if (offsetx + (mv.x >> 1) < 0 ||
1131 offsety + (mv.y >> 1) < 0 ||
1132 offsetx + width + (mv.x + 1 >> 1) > fwidth ||
1133 offsety + height + (mv.y + 1 >> 1) > fheight)
1134 return AVERROR_INVALIDDATA;
1138 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1139 (offsety + (mv.y >> 1)) * src_linesize;
1140 for (int y = 0; y < height; y++) {
1141 for (int x = 0; x < width; x++)
1143 dst += dst_linesize;
1144 src += src_linesize;
1148 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1149 (offsety + (mv.y >> 1)) * src_linesize;
1150 for (int y = 0; y < height; y++) {
1151 for (int x = 0; x < width; x++) {
1152 dst[x] = (uint8_t)((src[x] >> 1) + (src[x + 1] >> 1));
1155 dst += dst_linesize;
1156 src += src_linesize;
1160 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1161 (offsety + (mv.y >> 1)) * src_linesize;
1162 for (int y = 0; y < height; y++) {
1163 for (int x = 0; x < width; x++) {
1164 dst[x] = (uint8_t)((src[x] >> 1) + (src[x + src_linesize] >> 1));
1167 dst += dst_linesize;
1168 src += src_linesize;
1172 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1173 (offsety + (mv.y >> 1)) * src_linesize;
1174 for (int y = 0; y < height; y++) {
1175 for (int x = 0; x < width; x++) {
1176 dst[x] = (uint8_t)((((src[x] >> 1) + (src[x + 1] >> 1)) >> 1) +
1177 (((src[x + src_linesize] >> 1) + (src[x + 1 + src_linesize] >> 1)) >> 1));
1180 dst += dst_linesize;
1181 src += src_linesize;
1188 int adjx = index == 8 ? 0 : width / 2;
1189 int adjy = index == 8 ? height / 2 : 0;
1191 width = width - adjx;
1192 height = height - adjy;
1193 tidx = get_index(height) * 4 + get_index(width);
1195 for (int i = 0; i < 2; i++) {
1198 idx2 = get_vlc2(gb, mv_vlc[s->moflex][tidx].table,
1199 MOBI_MV_VLC_BITS, 1);
1201 ret = predict_motion(avctx, width, height, idx2,
1202 offsetm, offsetx + i * adjx, offsety + i * adjy);
1211 static int mobiclip_decode(AVCodecContext *avctx, void *data,
1212 int *got_frame, AVPacket *pkt)
1214 MobiClipContext *s = avctx->priv_data;
1215 GetBitContext *gb = &s->gb;
1216 AVFrame *frame = s->pic[s->current_pic];
1219 av_fast_padded_malloc(&s->bitstream, &s->bitstream_size,
1222 if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0)
1225 s->bdsp.bswap16_buf((uint16_t *)s->bitstream,
1226 (uint16_t *)pkt->data,
1227 (pkt->size + 1) >> 1);
1229 ret = init_get_bits8(gb, s->bitstream, FFALIGN(pkt->size, 2));
1233 if (get_bits1(gb)) {
1234 frame->pict_type = AV_PICTURE_TYPE_I;
1235 frame->key_frame = 1;
1236 s->moflex = get_bits1(gb);
1237 s->dct_tab_idx = get_bits1(gb);
1239 ret = setup_qtables(avctx, get_bits(gb, 6));
1243 for (int y = 0; y < avctx->height; y += 16) {
1244 for (int x = 0; x < avctx->width; x += 16) {
1245 ret = decode_macroblock(avctx, frame, x, y, get_bits1(gb));
1251 MotionXY *motion = s->motion;
1253 memset(motion, 0, s->motion_size);
1255 frame->pict_type = AV_PICTURE_TYPE_P;
1256 frame->key_frame = 0;
1259 ret = setup_qtables(avctx, s->quantizer + get_se_golomb(gb));
1263 for (int y = 0; y < avctx->height; y += 16) {
1264 for (int x = 0; x < avctx->width; x += 16) {
1267 motion[0].x = mid_pred(motion[x / 16 + 1].x, motion[x / 16 + 2].x, motion[x / 16 + 3].x);
1268 motion[0].y = mid_pred(motion[x / 16 + 1].y, motion[x / 16 + 2].y, motion[x / 16 + 3].y);
1269 motion[x / 16 + 2].x = 0;
1270 motion[x / 16 + 2].y = 0;
1272 idx = get_vlc2(gb, mv_vlc[s->moflex][0].table,
1273 MOBI_MV_VLC_BITS, 1);
1275 if (idx == 6 || idx == 7) {
1276 ret = decode_macroblock(avctx, frame, x, y, idx == 7);
1281 ret = predict_motion(avctx, 16, 16, idx, x / 16 + 2, x, y);
1284 idx2 = get_ue_golomb(gb);
1285 if (idx2 >= FF_ARRAY_ELEMS(pframe_block8x8_coefficients_tab))
1286 return AVERROR_INVALIDDATA;
1287 flags = pframe_block8x8_coefficients_tab[idx2];
1289 for (int sy = y; sy < y + 16; sy += 8) {
1290 for (int sx = x; sx < x + 16; sx += 8) {
1292 add_pframe_coefficients(avctx, frame, sx, sy, 8, 0);
1298 add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 1 + !s->moflex);
1301 add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 2 - !s->moflex);
1308 avctx->colorspace = AVCOL_SPC_YCGCO;
1310 s->current_pic = (s->current_pic + 1) % 6;
1311 ret = av_frame_ref(data, frame);
1319 static void mobiclip_flush(AVCodecContext *avctx)
1321 MobiClipContext *s = avctx->priv_data;
1323 for (int i = 0; i < 6; i++)
1324 av_frame_unref(s->pic[i]);
1327 static av_cold int mobiclip_close(AVCodecContext *avctx)
1329 MobiClipContext *s = avctx->priv_data;
1331 av_freep(&s->bitstream);
1332 s->bitstream_size = 0;
1333 av_freep(&s->motion);
1336 for (int i = 0; i < 6; i++) {
1337 av_frame_free(&s->pic[i]);
1343 AVCodec ff_mobiclip_decoder = {
1345 .long_name = NULL_IF_CONFIG_SMALL("MobiClip Video"),
1346 .type = AVMEDIA_TYPE_VIDEO,
1347 .id = AV_CODEC_ID_MOBICLIP,
1348 .priv_data_size = sizeof(MobiClipContext),
1349 .init = mobiclip_init,
1350 .decode = mobiclip_decode,
1351 .flush = mobiclip_flush,
1352 .close = mobiclip_close,
1353 .capabilities = AV_CODEC_CAP_DR1,
1354 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,