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"
28 #include "bytestream.h"
34 #define MOBI_MV_VLC_BITS 6
36 static const uint8_t zigzag4x4_tab[] =
38 0x00, 0x04, 0x01, 0x02, 0x05, 0x08, 0x0C, 0x09, 0x06, 0x03, 0x07, 0x0A,
39 0x0D, 0x0E, 0x0B, 0x0F
42 static const uint8_t quant4x4_tab[][16] =
44 { 10, 13, 13, 10, 16, 10, 13, 13, 13, 13, 16, 10, 16, 13, 13, 16 },
45 { 11, 14, 14, 11, 18, 11, 14, 14, 14, 14, 18, 11, 18, 14, 14, 18 },
46 { 13, 16, 16, 13, 20, 13, 16, 16, 16, 16, 20, 13, 20, 16, 16, 20 },
47 { 14, 18, 18, 14, 23, 14, 18, 18, 18, 18, 23, 14, 23, 18, 18, 23 },
48 { 16, 20, 20, 16, 25, 16, 20, 20, 20, 20, 25, 16, 25, 20, 20, 25 },
49 { 18, 23, 23, 18, 29, 18, 23, 23, 23, 23, 29, 18, 29, 23, 23, 29 },
52 static const uint8_t quant8x8_tab[][64] =
54 { 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,
55 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,},
56 { 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,
57 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,},
58 { 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,
59 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,},
60 { 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,
61 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,},
62 { 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,
63 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,},
64 { 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,
65 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,},
68 static const uint8_t block4x4_coefficients_tab[] =
70 15, 0, 2, 1, 4, 8, 12, 3, 11, 13, 14, 7, 10, 5, 9, 6,
73 static const uint8_t pframe_block4x4_coefficients_tab[] =
75 0, 4, 1, 8, 2, 12, 3, 5, 10, 15, 7, 13, 14, 11, 9, 6,
78 static const uint8_t block8x8_coefficients_tab[] =
80 0x00, 0x1F, 0x3F, 0x0F, 0x08, 0x04, 0x02, 0x01, 0x0B, 0x0E, 0x1B, 0x0D,
81 0x03, 0x07, 0x0C, 0x17, 0x1D, 0x0A, 0x1E, 0x05, 0x10, 0x2F, 0x37, 0x3B,
82 0x13, 0x3D, 0x3E, 0x09, 0x1C, 0x06, 0x15, 0x1A, 0x33, 0x11, 0x12, 0x14,
83 0x18, 0x20, 0x3C, 0x35, 0x19, 0x16, 0x3A, 0x30, 0x31, 0x32, 0x27, 0x34,
84 0x2B, 0x2D, 0x39, 0x38, 0x23, 0x36, 0x2E, 0x21, 0x25, 0x22, 0x24, 0x2C,
85 0x2A, 0x28, 0x29, 0x26,
88 static const uint8_t pframe_block8x8_coefficients_tab[] =
90 0x00, 0x0F, 0x04, 0x01, 0x08, 0x02, 0x0C, 0x03, 0x05, 0x0A, 0x0D, 0x07, 0x0E, 0x0B, 0x1F, 0x09,
91 0x06, 0x10, 0x3F, 0x1E, 0x17, 0x1D, 0x1B, 0x1C, 0x13, 0x18, 0x1A, 0x12, 0x11, 0x14, 0x15, 0x20,
92 0x2F, 0x16, 0x19, 0x37, 0x3D, 0x3E, 0x3B, 0x3C, 0x33, 0x35, 0x21, 0x24, 0x22, 0x28, 0x23, 0x2C,
93 0x30, 0x27, 0x2D, 0x25, 0x3A, 0x2B, 0x2E, 0x2A, 0x31, 0x34, 0x38, 0x32, 0x29, 0x26, 0x39, 0x36
96 static const uint8_t run_residue[2][256] =
99 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,
100 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,
101 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,
102 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,
103 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,
104 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,
105 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,
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,
109 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,
110 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,
111 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,
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 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,
114 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,
115 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,
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,
120 static const uint8_t bits0[] = {
121 9, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
122 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12,
123 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 10, 10, 9,
124 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
125 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
126 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6,
127 6, 6, 6, 6, 6, 6, 5, 5, 5, 4, 2, 3, 4, 4,
130 static const uint16_t codes0[] = {
131 0x0, 0x4, 0x5, 0x6, 0x7, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
132 0xB, 0xC, 0xD, 0xE, 0xF, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
133 0x26, 0x27, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
134 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x3, 0x20,
135 0x21, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
136 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23,
137 0x24, 0x25, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
138 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x10, 0x11, 0x12, 0x13, 0x14,
139 0x15, 0x16, 0x17, 0xC, 0xD, 0xE, 0xF, 0x10, 0x11, 0x12,
140 0x13, 0x14, 0x15, 0xB, 0xC, 0xD, 0x7, 0x2, 0x6, 0xE, 0xF,
143 static const uint16_t syms0[] = {
144 0x0, 0x822, 0x803, 0xB, 0xA, 0xB81, 0xB61, 0xB41, 0xB21, 0x122,
145 0x102, 0xE2, 0xC2, 0xA2, 0x63, 0x43, 0x24, 0xC, 0x25, 0x2E1, 0x301,
146 0xBA1, 0xBC1, 0xBE1, 0xC01, 0x26, 0x44, 0x83, 0xA3, 0xC3, 0x142,
147 0x321, 0x341, 0xC21, 0xC41, 0xC61, 0xC81, 0xCA1, 0xCC1, 0xCE1, 0xD01,
148 0x0, 0x9, 0x8, 0xB01, 0xAE1, 0xAC1, 0xAA1, 0xA81, 0xA61, 0xA41, 0xA21,
149 0x802, 0x2C1, 0x2A1, 0x281, 0x261, 0x241, 0x221, 0x201, 0x1E1, 0x82,
150 0x62, 0x7, 0x6, 0xA01, 0x9E1, 0x9C1, 0x9A1, 0x981, 0x961, 0x941, 0x921,
151 0x1C1, 0x1A1, 0x42, 0x23, 0x5, 0x901, 0x8E1, 0x8C1, 0x8A1, 0x181, 0x161,
152 0x141, 0x4, 0x881, 0x861, 0x841, 0x821, 0x121, 0x101, 0xE1, 0xC1, 0x22,
153 0x3, 0xA1, 0x81, 0x61, 0x801, 0x1, 0x21, 0x41, 0x2,
156 static const uint16_t syms1[] = {
157 0x0, 0x807, 0x806, 0x16, 0x15, 0x842, 0x823, 0x805, 0x1A1, 0xA3, 0x102, 0x83,
158 0x64, 0x44, 0x27, 0x14, 0x13, 0x17, 0x18, 0x28, 0x122, 0x862, 0x882, 0x9E1, 0xA01,
159 0x19, 0x1A, 0x1B, 0x29, 0xC3, 0x2A, 0x45, 0xE3, 0x1C1, 0x808, 0x8A2, 0x8C2, 0xA21,
160 0xA41, 0xA61, 0xA81, 0x0, 0x12, 0x11, 0x9C1, 0x9A1, 0x981, 0x961, 0x941, 0x822, 0x804,
161 0x181, 0x161, 0xE2, 0xC2, 0xA2, 0x63, 0x43, 0x26, 0x25, 0x10, 0x82, 0xF, 0xE, 0xD, 0x901,
162 0x8E1, 0x8C1, 0x803, 0x141, 0x121, 0x101, 0x921, 0x62, 0x24, 0xC, 0xB, 0xA, 0x881, 0x861,
163 0xC1, 0x8A1, 0xE1, 0x42, 0x23, 0x9, 0x802, 0xA1, 0x841, 0x821, 0x81, 0x61, 0x8, 0x7, 0x22,
164 0x6, 0x41, 0x5, 0x4, 0x801, 0x1, 0x2, 0x21, 0x3,
167 static const uint8_t mv_len[16] =
169 10, 8, 8, 7, 8, 8, 8, 7, 8, 8, 8, 7, 7, 7, 7, 6,
172 static const uint8_t mv_bits[16][10] =
174 { 1, 3, 3, 4, 4, 5, 5, 5, 6, 6 },
175 { 2, 2, 3, 3, 3, 4, 5, 5 },
176 { 2, 2, 3, 3, 4, 4, 4, 4 },
177 { 1, 3, 3, 4, 4, 4, 4 },
178 { 2, 2, 3, 3, 3, 4, 5, 5 },
179 { 2, 3, 3, 3, 3, 3, 4, 4 },
180 { 1, 3, 3, 4, 4, 4, 5, 5 },
181 { 1, 3, 3, 4, 4, 4, 4 },
182 { 2, 2, 3, 3, 4, 4, 4, 4 },
183 { 1, 3, 3, 4, 4, 4, 5, 5 },
184 { 2, 2, 3, 3, 4, 4, 4, 4 },
185 { 2, 2, 3, 3, 3, 4, 4 },
186 { 1, 3, 3, 4, 4, 4, 4 },
187 { 1, 3, 3, 4, 4, 4, 4 },
188 { 2, 2, 3, 3, 3, 4, 4 },
189 { 2, 2, 3, 3, 3, 3 },
192 static const uint8_t mv_codes[16][10] =
194 { 1, 0, 2, 2, 7, 6, 7, 12, 26, 27 },
195 { 0, 2, 2, 6, 7, 6, 14, 15 },
196 { 0, 3, 3, 4, 4, 5, 10, 11 },
197 { 0, 5, 7, 8, 9, 12, 13 },
198 { 1, 3, 0, 1, 5, 8, 18, 19 },
199 { 3, 0, 2, 3, 4, 5, 2, 3 },
200 { 0, 4, 5, 12, 13, 14, 30, 31 },
201 { 0, 5, 6, 8, 9, 14, 15 },
202 { 0, 3, 3, 4, 4, 5, 10, 11 },
203 { 0, 4, 5, 12, 13, 14, 30, 31 },
204 { 0, 3, 2, 5, 6, 7, 8, 9 },
205 { 0, 3, 2, 3, 5, 8, 9 },
206 { 0, 5, 6, 8, 9, 14, 15 },
207 { 0, 5, 6, 8, 9, 14, 15 },
208 { 0, 3, 2, 3, 5, 8, 9 },
209 { 0, 3, 2, 3, 4, 5 },
212 static const uint8_t mv_syms[16][10] =
214 { 0, 8, 1, 2, 9, 3, 6, 7, 5, 4 },
215 { 9, 1, 2, 8, 0, 3, 5, 4 },
216 { 0, 1, 2, 9, 5, 4, 3, 8 },
217 { 1, 2, 0, 5, 4, 8, 3 },
218 { 8, 1, 2, 9, 0, 3, 5, 4 },
219 { 1, 3, 2, 9, 8, 0, 5, 4 },
220 { 1, 2, 0, 9, 8, 3, 5, 4 },
221 { 1, 2, 0, 8, 5, 4, 3 },
222 { 0, 1, 2, 8, 5, 4, 3, 9 },
223 { 1, 2, 0, 9, 8, 3, 5, 4 },
224 { 0, 1, 3, 2, 9, 8, 5, 4 },
225 { 0, 1, 4, 3, 2, 8, 5 },
226 { 1, 2, 0, 5, 4, 9, 3 },
227 { 1, 2, 0, 9, 5, 4, 3 },
228 { 0, 1, 5, 3, 2, 9, 4 },
229 { 0, 1, 4, 5, 3, 2 },
232 static const uint8_t mv_bits_mods[16][10] =
234 { 2, 2, 3, 3, 4, 4, 5, 5, 5, 5 },
235 { 2, 2, 3, 3, 4, 4, 4, 4 },
236 { 2, 2, 3, 3, 4, 4, 4, 4 },
237 { 1, 3, 3, 3, 4, 5, 5 },
238 { 2, 2, 3, 3, 4, 4, 4, 4 },
239 { 2, 2, 3, 3, 4, 4, 4, 4 },
240 { 2, 2, 3, 3, 4, 4, 4, 4 },
241 { 2, 2, 2, 3, 4, 5, 5 },
242 { 2, 2, 3, 3, 4, 4, 4, 4 },
243 { 2, 2, 3, 3, 4, 4, 4, 4 },
244 { 2, 2, 3, 3, 3, 4, 5, 5 },
245 { 2, 2, 3, 3, 3, 4, 4 },
246 { 1, 3, 3, 4, 4, 4, 4 },
247 { 2, 2, 3, 3, 3, 4, 4 },
248 { 2, 2, 3, 3, 3, 4, 4 },
249 { 2, 2, 3, 3, 3, 3 },
252 static const uint8_t mv_codes_mods[16][10] =
254 { 0, 3, 2, 3, 9, 10, 16, 17, 22, 23 },
255 { 0, 3, 2, 4, 6, 7, 10, 11 },
256 { 1, 3, 0, 5, 2, 3, 8, 9 },
257 { 0, 4, 6, 7, 10, 22, 23 },
258 { 0, 3, 3, 4, 4, 5, 10, 11 },
259 { 0, 3, 2, 5, 6, 7, 8, 9 },
260 { 0, 3, 2, 5, 6, 7, 8, 9 },
261 { 0, 1, 3, 4, 10, 22, 23 },
262 { 0, 3, 2, 4, 6, 7, 10, 11 },
263 { 0, 3, 3, 5, 4, 5, 8, 9 },
264 { 0, 3, 2, 3, 5, 9, 16, 17 },
265 { 0, 3, 2, 4, 5, 6, 7 },
266 { 0, 5, 6, 8, 9, 14, 15 },
267 { 0, 3, 2, 4, 5, 6, 7 },
268 { 0, 3, 2, 4, 5, 6, 7 },
269 { 1, 2, 0, 1, 6, 7 },
272 static const uint8_t mv_syms_mods[16][10] =
274 { 1, 0, 8, 9, 2, 7, 4, 3, 5, 6 },
275 { 0, 1, 9, 2, 5, 4, 3, 8 },
276 { 0, 1, 3, 2, 9, 5, 4, 8 },
277 { 1, 3, 2, 0, 4, 8, 5 },
278 { 0, 1, 8, 2, 5, 4, 3, 9 },
279 { 0, 1, 3, 2, 5, 9, 4, 8 },
280 { 0, 1, 3, 2, 9, 5, 8, 4 },
281 { 0, 2, 1, 3, 4, 8, 5 },
282 { 0, 1, 3, 2, 8, 4, 5, 9 },
283 { 2, 1, 3, 0, 8, 9, 5, 4 },
284 { 0, 1, 4, 3, 2, 5, 8, 9 },
285 { 0, 1, 4, 3, 2, 8, 5 },
286 { 1, 2, 0, 9, 4, 5, 3 },
287 { 2, 1, 4, 3, 0, 9, 5 },
288 { 0, 1, 4, 3, 2, 9, 5 },
289 { 1, 0, 5, 4, 3, 2 },
292 typedef struct BlockXY {
301 typedef struct MotionXY {
305 typedef struct MobiClipContext {
326 BswapDSPContext bdsp;
329 static av_cold int mobiclip_init(AVCodecContext *avctx)
331 MobiClipContext *s = avctx->priv_data;
334 if (avctx->width & 15 || avctx->height & 15) {
335 av_log(avctx, AV_LOG_ERROR, "width/height not multiple of 16\n");
336 return AVERROR_INVALIDDATA;
339 ff_bswapdsp_init(&s->bdsp);
341 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
343 ret = ff_init_vlc_sparse(&s->vlc[0], 12, 104,
344 bits0, sizeof(*bits0), sizeof(*bits0),
345 codes0, sizeof(*codes0), sizeof(*codes0),
346 syms0, sizeof(*syms0), sizeof(*syms0), 0);
350 ret = ff_init_vlc_sparse(&s->vlc[1], 12, 104,
351 bits0, sizeof(*bits0), sizeof(*bits0),
352 codes0, sizeof(*codes0), sizeof(*codes0),
353 syms1, sizeof(*syms1), sizeof(*syms1), 0);
357 s->motion = av_calloc(avctx->width / 16 + 3, sizeof(MotionXY));
359 return AVERROR(ENOMEM);
360 s->motion_size = (avctx->width / 16 + 3) * sizeof(MotionXY);
362 for (int i = 0; i < 6; i++) {
363 s->pic[i] = av_frame_alloc();
365 return AVERROR(ENOMEM);
368 for (int j = 0; j < 16; j++) {
369 ret = ff_init_vlc_sparse(&s->mv_vlc[0][j], MOBI_MV_VLC_BITS, mv_len[j],
370 mv_bits_mods[j], sizeof(*mv_bits_mods[j]), sizeof(*mv_bits_mods[j]),
371 mv_codes_mods[j], sizeof(*mv_codes_mods[j]), sizeof(*mv_codes_mods[j]),
372 mv_syms_mods[j], sizeof(*mv_syms_mods[j]), sizeof(*mv_syms_mods[j]), 0);
376 ret = ff_init_vlc_sparse(&s->mv_vlc[1][j], MOBI_MV_VLC_BITS, mv_len[j],
377 mv_bits[j], sizeof(*mv_bits[j]), sizeof(*mv_bits[j]),
378 mv_codes[j], sizeof(*mv_codes[j]), sizeof(*mv_codes[j]),
379 mv_syms[j], sizeof(*mv_syms[j]), sizeof(*mv_syms[j]), 0);
387 static int setup_qtables(AVCodecContext *avctx, int quantizer)
389 MobiClipContext *s = avctx->priv_data;
392 if (quantizer < 12 || quantizer > 161)
393 return AVERROR_INVALIDDATA;
395 s->quantizer = quantizer;
400 for (int i = 0; i < 16; i++)
401 s->qtab[0][i] = quant4x4_tab[qx][i] << qy;
403 for (int i = 0; i < 64; i++)
404 s->qtab[1][i] = quant8x8_tab[qx][i] << (qy - 2);
406 for (int i = 0; i < 20; i++)
412 static void inverse4(unsigned *rs)
414 unsigned a = rs[0] + rs[2];
415 unsigned b = rs[0] - rs[2];
416 unsigned c = rs[1] + ((int)rs[3] >> 1);
417 unsigned d = ((int)rs[1] >> 1) - rs[3];
425 static void idct(int *arr, int size)
428 unsigned x3, x2, x1, x0;
443 e = (unsigned)arr[7] + arr[1] - arr[3] - (arr[3] >> 1);
444 f = (unsigned)arr[7] - arr[1] + arr[5] + (arr[5] >> 1);
445 g = (unsigned)arr[5] - arr[3] - arr[7] - (arr[7] >> 1);
446 h = (unsigned)arr[5] + arr[3] + arr[1] + (arr[1] >> 1);
447 x3 = (unsigned)g + (h >> 2);
448 x2 = (unsigned)e + (f >> 2);
449 x1 = (e >> 2) - (unsigned)f;
450 x0 = (unsigned)h - (g >> 2);
452 arr[0] = tmp[0] + x0;
453 arr[1] = tmp[1] + x1;
454 arr[2] = tmp[2] + x2;
455 arr[3] = tmp[3] + x3;
456 arr[4] = tmp[3] - x3;
457 arr[5] = tmp[2] - x2;
458 arr[6] = tmp[1] - x1;
459 arr[7] = tmp[0] - x0;
462 static int read_run_encoding(AVCodecContext *avctx,
463 int *last, int *run, int *level)
465 MobiClipContext *s = avctx->priv_data;
466 GetBitContext *gb = &s->gb;
467 int n = get_vlc2(gb, s->vlc[s->dct_tab_idx].table,
468 s->vlc[s->dct_tab_idx].bits, 2);
471 return AVERROR_INVALIDDATA;
473 *last = (n >> 11) == 1;
474 *run = (n >> 5) & 0x3F;
480 static int add_coefficients(AVCodecContext *avctx, AVFrame *frame,
481 int bx, int by, int size, int plane)
483 MobiClipContext *s = avctx->priv_data;
484 GetBitContext *gb = &s->gb;
486 const uint8_t *ztab = size == 8 ? ff_zigzag_direct : zigzag4x4_tab;
487 const int *qtab = s->qtab[size == 8];
488 uint8_t *dst = frame->data[plane] + by * frame->linesize[plane] + bx;
491 for (int pos = 0; get_bits_left(gb) > 0; pos++) {
492 int qval, last, run, level;
494 ret = read_run_encoding(avctx, &last, &run, &level);
501 } else if (!get_bits1(gb)) {
502 ret = read_run_encoding(avctx, &last, &run, &level);
505 level += run_residue[s->dct_tab_idx][(last ? 64 : 0) + run];
508 } else if (!get_bits1(gb)) {
509 ret = read_run_encoding(avctx, &last, &run, &level);
512 run += run_residue[s->dct_tab_idx][128 + (last ? 64 : 0) + level];
516 last = get_bits1(gb);
517 run = get_bits(gb, 6);
518 level = get_sbits(gb, 12);
522 if (pos >= size * size)
523 return AVERROR_INVALIDDATA;
525 mat[ztab[pos]] = qval *(unsigned)level;
532 for (int y = 0; y < size; y++)
533 idct(&mat[y * size], size);
535 for (int y = 0; y < size; y++) {
536 for (int x = y + 1; x < size; x++) {
537 int a = mat[x * size + y];
538 int b = mat[y * size + x];
540 mat[y * size + x] = a;
541 mat[x * size + y] = b;
544 idct(&mat[y * size], size);
545 for (int x = 0; x < size; x++)
546 dst[x] = av_clip_uint8(dst[x] + (mat[y * size + x] >> 6));
547 dst += frame->linesize[plane];
553 static int add_pframe_coefficients(AVCodecContext *avctx, AVFrame *frame,
554 int bx, int by, int size, int plane)
556 MobiClipContext *s = avctx->priv_data;
557 GetBitContext *gb = &s->gb;
558 int ret, idx = get_ue_golomb(gb);
561 ret = add_coefficients(avctx, frame, bx, by, size, plane);
562 } else if (idx < FF_ARRAY_ELEMS(pframe_block4x4_coefficients_tab)) {
563 int flags = pframe_block4x4_coefficients_tab[idx];
565 for (int y = by; y < by + 8; y += 4) {
566 for (int x = bx; x < bx + 8; x += 4) {
568 ret = add_coefficients(avctx, frame, x, y, 4, plane);
576 ret = AVERROR_INVALIDDATA;
582 static int adjust(int x, int size)
584 return size == 16 ? (x + 1) >> 1 : x;
587 static uint8_t pget(BlockXY b)
592 if (b.x == -1 && b.y >= b.size) {
593 ret.x = -1, ret.y = b.size - 1;
594 } else if (b.x >= -1 && b.y >= -1) {
595 ret.x = b.x, ret.y = b.y;
596 } else if (b.x == -1 && b.y == -2) {
597 ret.x = 0, ret.y = -1;
598 } else if (b.x == -2 && b.y == -1) {
599 ret.x = -1, ret.y = 0;
602 y = av_clip(ret.ay + ret.y, 0, ret.h - 1);
603 x = av_clip(ret.ax + ret.x, 0, ret.w - 1);
605 return ret.block[y * ret.linesize + x];
608 static uint8_t half(int a, int b)
610 return ((a + b) + 1) / 2;
613 static uint8_t half3(int a, int b, int c)
615 return ((a + b + b + c) * 2 / 4 + 1) / 2;;
618 static uint8_t pick_above(BlockXY bxy)
625 static uint8_t pick_left(BlockXY bxy)
632 static uint8_t half_horz(BlockXY bxy)
634 BlockXY a = bxy, b = bxy, c = bxy;
639 return half3(pget(a), pget(b), pget(c));
642 static uint8_t half_vert(BlockXY bxy)
644 BlockXY a = bxy, b = bxy, c = bxy;
649 return half3(pget(a), pget(b), pget(c));
652 static uint8_t pick_4(BlockXY bxy)
656 if ((bxy.x % 2) == 0) {
662 ba.y = bxy.y + bxy.x / 2;
667 bb.y = bxy.y + bxy.x / 2 + 1;
676 ba.y = bxy.y + bxy.x / 2 + 1;
683 static uint8_t pick_5(BlockXY bxy)
696 val = half(pget(a), pget(b));
697 } else if (bxy.y == 0) {
704 } else if (bxy.x == 1) {
723 static uint8_t pick_6(BlockXY bxy)
736 val = half(pget(a), pget(b));
737 } else if (bxy.x == 0) {
744 } else if (bxy.y == 1) {
763 static uint8_t pick_7(BlockXY bxy)
792 return half3(acc1, clr, acc2);
795 static uint8_t pick_8(BlockXY bxy)
813 } else if (bxy.y == 1) {
818 } else if (bxy.x < bxy.size - 1) {
823 } else if (bxy.y % 2 == 0) {
826 ba.x = bxy.y / 2 + bxy.size - 1;
830 bb.x = bxy.y / 2 + bxy.size;
837 ba.x = bxy.y / 2 + bxy.size;
846 static void block_fill_simple(uint8_t *block, int size, int linesize, int fill)
848 for (int y = 0; y < size; y++) {
849 memset(block, fill, size);
854 static void block_fill(uint8_t *block, int size, int linesize,
855 int w, int h, int ax, int ay,
856 uint8_t (*pick)(BlockXY bxy))
862 bxy.linesize = linesize;
868 for (int y = 0; y < size; y++) {
870 for (int x = 0; x < size; x++) {
877 block[ax + x + (ay + y) * linesize] = val;
882 static int block_sum(const uint8_t *block, int w, int h, int linesize)
886 for (int y = 0; y < h; y++) {
887 for (int x = 0; x < w; x++) {
896 static int predict_intra(AVCodecContext *avctx, AVFrame *frame, int ax, int ay,
897 int pmode, int add_coeffs, int size, int plane)
899 MobiClipContext *s = avctx->priv_data;
900 GetBitContext *gb = &s->gb;
901 int w = avctx->width >> !!plane, h = avctx->height >> !!plane;
906 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_above);
909 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_left);
915 uint8_t *top = frame->data[plane] + FFMAX(ay - 1, 0) * frame->linesize[plane] + ax;
916 uint8_t *left = frame->data[plane] + ay * frame->linesize[plane] + FFMAX(ax - 1, 0);
917 int bottommost = frame->data[plane][(ay + size - 1) * frame->linesize[plane] + FFMAX(ax - 1, 0)];
918 int rightmost = frame->data[plane][FFMAX(ay - 1, 0) * frame->linesize[plane] + ax + size - 1];
919 int avg = (bottommost + rightmost + 1) / 2 + 2 * get_se_golomb(gb);
920 int r6 = adjust(avg - bottommost, size);
921 int r9 = adjust(avg - rightmost, size);
922 int shift = adjust(size, size) == 8 ? 3 : 2;
925 for (int x = 0; x < size; x++) {
927 arr1[x] = adjust(((bottommost - val) * (1 << shift)) + r6 * (x + 1), size);
930 for (int y = 0; y < size; y++) {
931 int val = left[y * frame->linesize[plane]];
932 arr2[y] = adjust(((rightmost - val) * (1 << shift)) + r9 * (y + 1), size);
935 block = frame->data[plane] + ay * frame->linesize[plane] + ax;
936 for (int y = 0; y < size; y++) {
937 for (int x = 0; x < size; x++) {
938 block[x] = (((top[x] + left[0] + ((arr1[x] * (y + 1) +
939 arr2[y] * (x + 1)) >> 2 * shift)) + 1) / 2) & 0xFF;
941 block += frame->linesize[plane];
942 left += frame->linesize[plane];
950 if (ax == 0 && ay == 0) {
952 } else if (ax >= 1 && ay >= 1) {
953 int left = block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1,
954 1, size, frame->linesize[plane]);
955 int top = block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax,
956 size, 1, frame->linesize[plane]);
958 fill = ((left + top) * 2 / (2 * size) + 1) / 2;
959 } else if (ax >= 1) {
960 fill = (block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1,
961 1, size, frame->linesize[plane]) * 2 / size + 1) / 2;
962 } else if (ay >= 1) {
963 fill = (block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax,
964 size, 1, frame->linesize[plane]) * 2 / size + 1) / 2;
969 block_fill_simple(frame->data[plane] + ay * frame->linesize[plane] + ax,
970 size, frame->linesize[plane], fill);
974 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_4);
977 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_5);
980 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_6);
983 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_7);
986 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_8);
991 ret = add_coefficients(avctx, frame, ax, ay, size, plane);
996 static int get_prediction(AVCodecContext *avctx, int x, int y, int size)
998 MobiClipContext *s = avctx->priv_data;
999 GetBitContext *gb = &s->gb;
1000 int index = (y & 0xC) | (x / 4 % 4);
1002 uint8_t val = FFMIN(s->pre[index], index % 4 == 0 ? 9 : s->pre[index + 3]);
1006 if (!get_bits1(gb)) {
1007 int x = get_bits(gb, 3);
1008 val = x + (x >= val ? 1 : 0);
1011 s->pre[index + 4] = val;
1013 s->pre[index + 5] = s->pre[index + 8] = s->pre[index + 9] = val;
1018 static int process_block(AVCodecContext *avctx, AVFrame *frame,
1019 int x, int y, int pmode, int has_coeffs, int plane)
1021 MobiClipContext *s = avctx->priv_data;
1022 GetBitContext *gb = &s->gb;
1027 pmode = get_prediction(avctx, x, y, 8);
1028 return predict_intra(avctx, frame, x, y, pmode, 0, 8, plane);
1031 tmp = get_ue_golomb(gb);
1032 if (tmp < 0 || tmp > FF_ARRAY_ELEMS(block4x4_coefficients_tab))
1033 return AVERROR_INVALIDDATA;
1037 pmode = get_prediction(avctx, x, y, 8);
1038 ret = predict_intra(avctx, frame, x, y, pmode, 1, 8, plane);
1040 int flags = block4x4_coefficients_tab[tmp - 1];
1042 for (int by = y; by < y + 8; by += 4) {
1043 for (int bx = x; bx < x + 8; bx += 4) {
1044 int new_pmode = pmode;
1047 new_pmode = get_prediction(avctx, bx, by, 4);
1048 ret = predict_intra(avctx, frame, bx, by, new_pmode, flags & 1, 4, plane);
1059 static int decode_macroblock(AVCodecContext *avctx, AVFrame *frame,
1060 int x, int y, int predict)
1062 MobiClipContext *s = avctx->priv_data;
1063 GetBitContext *gb = &s->gb;
1064 int flags, pmode_uv, idx = get_ue_golomb(gb);
1067 if (idx < 0 || idx >= FF_ARRAY_ELEMS(block8x8_coefficients_tab))
1068 return AVERROR_INVALIDDATA;
1070 flags = block8x8_coefficients_tab[idx];
1073 ret = process_block(avctx, frame, x, y, -1, flags & 1, 0);
1077 ret = process_block(avctx, frame, x + 8, y, -1, flags & 1, 0);
1081 ret = process_block(avctx, frame, x, y + 8, -1, flags & 1, 0);
1085 ret = process_block(avctx, frame, x + 8, y + 8, -1, flags & 1, 0);
1090 int pmode = get_bits(gb, 3);
1093 ret = predict_intra(avctx, frame, x, y, pmode, 0, 16, 0);
1099 ret = process_block(avctx, frame, x, y, pmode, flags & 1, 0);
1103 ret = process_block(avctx, frame, x + 8, y, pmode, flags & 1, 0);
1107 ret = process_block(avctx, frame, x, y + 8, pmode, flags & 1, 0);
1111 ret = process_block(avctx, frame, x + 8, y + 8, pmode, flags & 1, 0);
1117 pmode_uv = get_bits(gb, 3);
1118 if (pmode_uv == 2) {
1119 ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 1 + !s->moflex);
1122 ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 2 - !s->moflex);
1128 ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 1 + !s->moflex);
1132 ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 2 - !s->moflex);
1139 static int get_index(int x)
1141 return x == 16 ? 0 : x == 8 ? 1 : x == 4 ? 2 : x == 2 ? 3 : 0;
1144 static int predict_motion(AVCodecContext *avctx,
1145 int width, int height, int index,
1146 int offsetm, int offsetx, int offsety)
1148 MobiClipContext *s = avctx->priv_data;
1149 MotionXY *motion = s->motion;
1150 GetBitContext *gb = &s->gb;
1151 int fheight = avctx->height;
1152 int fwidth = avctx->width;
1155 int sidx = -FFMAX(1, index) + s->current_pic;
1156 MotionXY mv = s->motion[0];
1162 mv.x = mv.x + get_se_golomb(gb);
1163 mv.y = mv.y + get_se_golomb(gb);
1166 motion[offsetm].x = mv.x;
1167 motion[offsetm].y = mv.y;
1169 for (int i = 0; i < 3; i++) {
1170 int method, src_linesize, dst_linesize;
1174 offsetx = offsetx >> 1;
1175 offsety = offsety >> 1;
1179 height = height >> 1;
1180 fwidth = fwidth >> 1;
1181 fheight = fheight >> 1;
1184 av_assert0(s->pic[sidx]);
1185 av_assert0(s->pic[s->current_pic]);
1186 av_assert0(s->pic[s->current_pic]->data[i]);
1187 if (!s->pic[sidx]->data[i])
1188 return AVERROR_INVALIDDATA;
1190 method = (mv.x & 1) | ((mv.y & 1) << 1);
1191 src_linesize = s->pic[sidx]->linesize[i];
1192 dst_linesize = s->pic[s->current_pic]->linesize[i];
1193 dst = s->pic[s->current_pic]->data[i] + offsetx + offsety * dst_linesize;
1195 if (offsetx + (mv.x >> 1) < 0 ||
1196 offsety + (mv.y >> 1) < 0 ||
1197 offsetx + width + (mv.x + 1 >> 1) > fwidth ||
1198 offsety + height + (mv.y + 1 >> 1) > fheight)
1199 return AVERROR_INVALIDDATA;
1203 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1204 (offsety + (mv.y >> 1)) * src_linesize;
1205 for (int y = 0; y < height; y++) {
1206 for (int x = 0; x < width; x++)
1208 dst += dst_linesize;
1209 src += src_linesize;
1213 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1214 (offsety + (mv.y >> 1)) * src_linesize;
1215 for (int y = 0; y < height; y++) {
1216 for (int x = 0; x < width; x++) {
1217 dst[x] = (uint8_t)((src[x] >> 1) + (src[x + 1] >> 1));
1220 dst += dst_linesize;
1221 src += src_linesize;
1225 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1226 (offsety + (mv.y >> 1)) * src_linesize;
1227 for (int y = 0; y < height; y++) {
1228 for (int x = 0; x < width; x++) {
1229 dst[x] = (uint8_t)((src[x] >> 1) + (src[x + src_linesize] >> 1));
1232 dst += dst_linesize;
1233 src += src_linesize;
1237 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1238 (offsety + (mv.y >> 1)) * src_linesize;
1239 for (int y = 0; y < height; y++) {
1240 for (int x = 0; x < width; x++) {
1241 dst[x] = (uint8_t)((((src[x] >> 1) + (src[x + 1] >> 1)) >> 1) +
1242 (((src[x + src_linesize] >> 1) + (src[x + 1 + src_linesize] >> 1)) >> 1));
1245 dst += dst_linesize;
1246 src += src_linesize;
1253 int adjx = index == 8 ? 0 : width / 2;
1254 int adjy = index == 8 ? height / 2 : 0;
1256 width = width - adjx;
1257 height = height - adjy;
1258 tidx = get_index(height) * 4 + get_index(width);
1260 for (int i = 0; i < 2; i++) {
1263 idx2 = get_vlc2(gb, s->mv_vlc[s->moflex][tidx].table,
1264 MOBI_MV_VLC_BITS, 1);
1266 return AVERROR_INVALIDDATA;
1268 ret = predict_motion(avctx, width, height, idx2,
1269 offsetm, offsetx + i * adjx, offsety + i * adjy);
1278 static int mobiclip_decode(AVCodecContext *avctx, void *data,
1279 int *got_frame, AVPacket *pkt)
1281 MobiClipContext *s = avctx->priv_data;
1282 GetBitContext *gb = &s->gb;
1283 AVFrame *frame = s->pic[s->current_pic];
1286 av_fast_padded_malloc(&s->bitstream, &s->bitstream_size,
1289 if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0)
1292 s->bdsp.bswap16_buf((uint16_t *)s->bitstream,
1293 (uint16_t *)pkt->data,
1294 (pkt->size + 1) >> 1);
1296 ret = init_get_bits8(gb, s->bitstream, FFALIGN(pkt->size, 2));
1300 if (get_bits1(gb)) {
1301 frame->pict_type = AV_PICTURE_TYPE_I;
1302 frame->key_frame = 1;
1303 s->moflex = get_bits1(gb);
1304 s->dct_tab_idx = get_bits1(gb);
1306 ret = setup_qtables(avctx, get_bits(gb, 6));
1310 for (int y = 0; y < avctx->height; y += 16) {
1311 for (int x = 0; x < avctx->width; x += 16) {
1312 ret = decode_macroblock(avctx, frame, x, y, get_bits1(gb));
1318 MotionXY *motion = s->motion;
1320 memset(motion, 0, s->motion_size);
1322 frame->pict_type = AV_PICTURE_TYPE_P;
1323 frame->key_frame = 0;
1326 ret = setup_qtables(avctx, s->quantizer + get_se_golomb(gb));
1330 for (int y = 0; y < avctx->height; y += 16) {
1331 for (int x = 0; x < avctx->width; x += 16) {
1334 motion[0].x = mid_pred(motion[x / 16 + 1].x, motion[x / 16 + 2].x, motion[x / 16 + 3].x);
1335 motion[0].y = mid_pred(motion[x / 16 + 1].y, motion[x / 16 + 2].y, motion[x / 16 + 3].y);
1336 motion[x / 16 + 2].x = 0;
1337 motion[x / 16 + 2].y = 0;
1339 idx = get_vlc2(gb, s->mv_vlc[s->moflex][0].table,
1340 MOBI_MV_VLC_BITS, 1);
1342 return AVERROR_INVALIDDATA;
1344 if (idx == 6 || idx == 7) {
1345 ret = decode_macroblock(avctx, frame, x, y, idx == 7);
1350 ret = predict_motion(avctx, 16, 16, idx, x / 16 + 2, x, y);
1353 idx2 = get_ue_golomb(gb);
1354 if (idx2 >= FF_ARRAY_ELEMS(pframe_block8x8_coefficients_tab))
1355 return AVERROR_INVALIDDATA;
1356 flags = pframe_block8x8_coefficients_tab[idx2];
1358 for (int sy = y; sy < y + 16; sy += 8) {
1359 for (int sx = x; sx < x + 16; sx += 8) {
1361 add_pframe_coefficients(avctx, frame, sx, sy, 8, 0);
1367 add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 1 + !s->moflex);
1370 add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 2 - !s->moflex);
1377 avctx->colorspace = AVCOL_SPC_YCGCO;
1379 s->current_pic = (s->current_pic + 1) % 6;
1380 ret = av_frame_ref(data, frame);
1388 static void mobiclip_flush(AVCodecContext *avctx)
1390 MobiClipContext *s = avctx->priv_data;
1392 for (int i = 0; i < 6; i++)
1393 av_frame_unref(s->pic[i]);
1396 static av_cold int mobiclip_close(AVCodecContext *avctx)
1398 MobiClipContext *s = avctx->priv_data;
1400 ff_free_vlc(&s->vlc[0]);
1401 ff_free_vlc(&s->vlc[1]);
1403 for (int i = 0; i < 16; i++) {
1404 ff_free_vlc(&s->mv_vlc[0][i]);
1405 ff_free_vlc(&s->mv_vlc[1][i]);
1408 av_freep(&s->bitstream);
1409 s->bitstream_size = 0;
1410 av_freep(&s->motion);
1413 for (int i = 0; i < 6; i++) {
1414 av_frame_free(&s->pic[i]);
1420 AVCodec ff_mobiclip_decoder = {
1422 .long_name = NULL_IF_CONFIG_SMALL("MobiClip Video"),
1423 .type = AVMEDIA_TYPE_VIDEO,
1424 .id = AV_CODEC_ID_MOBICLIP,
1425 .priv_data_size = sizeof(MobiClipContext),
1426 .init = mobiclip_init,
1427 .decode = mobiclip_decode,
1428 .flush = mobiclip_flush,
1429 .close = mobiclip_close,
1430 .capabilities = AV_CODEC_CAP_DR1,
1431 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,