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 static const uint8_t zigzag4x4_tab[] =
36 0x00, 0x04, 0x01, 0x02, 0x05, 0x08, 0x0C, 0x09, 0x06, 0x03, 0x07, 0x0A,
37 0x0D, 0x0E, 0x0B, 0x0F
40 static const uint8_t quant4x4_tab[][16] =
42 { 10, 13, 13, 10, 16, 10, 13, 13, 13, 13, 16, 10, 16, 13, 13, 16 },
43 { 11, 14, 14, 11, 18, 11, 14, 14, 14, 14, 18, 11, 18, 14, 14, 18 },
44 { 13, 16, 16, 13, 20, 13, 16, 16, 16, 16, 20, 13, 20, 16, 16, 20 },
45 { 14, 18, 18, 14, 23, 14, 18, 18, 18, 18, 23, 14, 23, 18, 18, 23 },
46 { 16, 20, 20, 16, 25, 16, 20, 20, 20, 20, 25, 16, 25, 20, 20, 25 },
47 { 18, 23, 23, 18, 29, 18, 23, 23, 23, 23, 29, 18, 29, 23, 23, 29 },
50 static const uint8_t quant8x8_tab[][64] =
52 { 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,
53 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,},
54 { 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,
55 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,},
56 { 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,
57 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,},
58 { 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,
59 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,},
60 { 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,
61 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,},
62 { 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,
63 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,},
66 static const uint8_t block4x4_coefficients_tab[] =
68 15, 0, 2, 1, 4, 8, 12, 3, 11, 13, 14, 7, 10, 5, 9, 6,
71 static const uint8_t pframe_block4x4_coefficients_tab[] =
73 0, 4, 1, 8, 2, 12, 3, 5, 10, 15, 7, 13, 14, 11, 9, 6,
76 static const uint8_t block8x8_coefficients_tab[] =
78 0x00, 0x1F, 0x3F, 0x0F, 0x08, 0x04, 0x02, 0x01, 0x0B, 0x0E, 0x1B, 0x0D,
79 0x03, 0x07, 0x0C, 0x17, 0x1D, 0x0A, 0x1E, 0x05, 0x10, 0x2F, 0x37, 0x3B,
80 0x13, 0x3D, 0x3E, 0x09, 0x1C, 0x06, 0x15, 0x1A, 0x33, 0x11, 0x12, 0x14,
81 0x18, 0x20, 0x3C, 0x35, 0x19, 0x16, 0x3A, 0x30, 0x31, 0x32, 0x27, 0x34,
82 0x2B, 0x2D, 0x39, 0x38, 0x23, 0x36, 0x2E, 0x21, 0x25, 0x22, 0x24, 0x2C,
83 0x2A, 0x28, 0x29, 0x26,
86 static const uint8_t pframe_block8x8_coefficients_tab[] =
88 0x00, 0x0F, 0x04, 0x01, 0x08, 0x02, 0x0C, 0x03, 0x05, 0x0A, 0x0D, 0x07, 0x0E, 0x0B, 0x1F, 0x09,
89 0x06, 0x10, 0x3F, 0x1E, 0x17, 0x1D, 0x1B, 0x1C, 0x13, 0x18, 0x1A, 0x12, 0x11, 0x14, 0x15, 0x20,
90 0x2F, 0x16, 0x19, 0x37, 0x3D, 0x3E, 0x3B, 0x3C, 0x33, 0x35, 0x21, 0x24, 0x22, 0x28, 0x23, 0x2C,
91 0x30, 0x27, 0x2D, 0x25, 0x3A, 0x2B, 0x2E, 0x2A, 0x31, 0x34, 0x38, 0x32, 0x29, 0x26, 0x39, 0x36
94 static const uint8_t run_residue[2][256] =
97 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,
98 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,
99 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,
100 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,
101 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,
102 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,
103 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,
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,
107 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,
108 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,
109 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,
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 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,
112 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,
113 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,
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,
118 static const uint8_t bits0[] = {
119 9, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
120 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12,
121 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 10, 10, 9,
122 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
123 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
124 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6,
125 6, 6, 6, 6, 6, 6, 5, 5, 5, 4, 2, 3, 4, 4,
128 static const uint16_t codes0[] = {
129 0x0, 0x4, 0x5, 0x6, 0x7, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
130 0xB, 0xC, 0xD, 0xE, 0xF, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
131 0x26, 0x27, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
132 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x3, 0x20,
133 0x21, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
134 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23,
135 0x24, 0x25, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
136 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x10, 0x11, 0x12, 0x13, 0x14,
137 0x15, 0x16, 0x17, 0xC, 0xD, 0xE, 0xF, 0x10, 0x11, 0x12,
138 0x13, 0x14, 0x15, 0xB, 0xC, 0xD, 0x7, 0x2, 0x6, 0xE, 0xF,
141 static const uint16_t syms0[] = {
142 0x0, 0x822, 0x803, 0xB, 0xA, 0xB81, 0xB61, 0xB41, 0xB21, 0x122,
143 0x102, 0xE2, 0xC2, 0xA2, 0x63, 0x43, 0x24, 0xC, 0x25, 0x2E1, 0x301,
144 0xBA1, 0xBC1, 0xBE1, 0xC01, 0x26, 0x44, 0x83, 0xA3, 0xC3, 0x142,
145 0x321, 0x341, 0xC21, 0xC41, 0xC61, 0xC81, 0xCA1, 0xCC1, 0xCE1, 0xD01,
146 0x0, 0x9, 0x8, 0xB01, 0xAE1, 0xAC1, 0xAA1, 0xA81, 0xA61, 0xA41, 0xA21,
147 0x802, 0x2C1, 0x2A1, 0x281, 0x261, 0x241, 0x221, 0x201, 0x1E1, 0x82,
148 0x62, 0x7, 0x6, 0xA01, 0x9E1, 0x9C1, 0x9A1, 0x981, 0x961, 0x941, 0x921,
149 0x1C1, 0x1A1, 0x42, 0x23, 0x5, 0x901, 0x8E1, 0x8C1, 0x8A1, 0x181, 0x161,
150 0x141, 0x4, 0x881, 0x861, 0x841, 0x821, 0x121, 0x101, 0xE1, 0xC1, 0x22,
151 0x3, 0xA1, 0x81, 0x61, 0x801, 0x1, 0x21, 0x41, 0x2,
154 static const uint16_t syms1[] = {
155 0x0, 0x807, 0x806, 0x16, 0x15, 0x842, 0x823, 0x805, 0x1A1, 0xA3, 0x102, 0x83,
156 0x64, 0x44, 0x27, 0x14, 0x13, 0x17, 0x18, 0x28, 0x122, 0x862, 0x882, 0x9E1, 0xA01,
157 0x19, 0x1A, 0x1B, 0x29, 0xC3, 0x2A, 0x45, 0xE3, 0x1C1, 0x808, 0x8A2, 0x8C2, 0xA21,
158 0xA41, 0xA61, 0xA81, 0x0, 0x12, 0x11, 0x9C1, 0x9A1, 0x981, 0x961, 0x941, 0x822, 0x804,
159 0x181, 0x161, 0xE2, 0xC2, 0xA2, 0x63, 0x43, 0x26, 0x25, 0x10, 0x82, 0xF, 0xE, 0xD, 0x901,
160 0x8E1, 0x8C1, 0x803, 0x141, 0x121, 0x101, 0x921, 0x62, 0x24, 0xC, 0xB, 0xA, 0x881, 0x861,
161 0xC1, 0x8A1, 0xE1, 0x42, 0x23, 0x9, 0x802, 0xA1, 0x841, 0x821, 0x81, 0x61, 0x8, 0x7, 0x22,
162 0x6, 0x41, 0x5, 0x4, 0x801, 0x1, 0x2, 0x21, 0x3,
165 static const uint8_t mv_len[16] =
167 10, 8, 8, 7, 8, 8, 8, 7, 8, 8, 8, 7, 7, 7, 7, 6,
170 static const uint8_t mv_bits[16][10] =
172 { 1, 3, 3, 4, 4, 5, 5, 5, 6, 6 },
173 { 2, 2, 3, 3, 3, 4, 5, 5 },
174 { 2, 2, 3, 3, 4, 4, 4, 4 },
175 { 1, 3, 3, 4, 4, 4, 4 },
176 { 2, 2, 3, 3, 3, 4, 5, 5 },
177 { 2, 3, 3, 3, 3, 3, 4, 4 },
178 { 1, 3, 3, 4, 4, 4, 5, 5 },
179 { 1, 3, 3, 4, 4, 4, 4 },
180 { 2, 2, 3, 3, 4, 4, 4, 4 },
181 { 1, 3, 3, 4, 4, 4, 5, 5 },
182 { 2, 2, 3, 3, 4, 4, 4, 4 },
183 { 2, 2, 3, 3, 3, 4, 4 },
184 { 1, 3, 3, 4, 4, 4, 4 },
185 { 1, 3, 3, 4, 4, 4, 4 },
186 { 2, 2, 3, 3, 3, 4, 4 },
187 { 2, 2, 3, 3, 3, 3 },
190 static const uint8_t mv_codes[16][10] =
192 { 1, 0, 2, 2, 7, 6, 7, 12, 26, 27 },
193 { 0, 2, 2, 6, 7, 6, 14, 15 },
194 { 0, 3, 3, 4, 4, 5, 10, 11 },
195 { 0, 5, 7, 8, 9, 12, 13 },
196 { 1, 3, 0, 1, 5, 8, 18, 19 },
197 { 3, 0, 2, 3, 4, 5, 2, 3 },
198 { 0, 4, 5, 12, 13, 14, 30, 31 },
199 { 0, 5, 6, 8, 9, 14, 15 },
200 { 0, 3, 3, 4, 4, 5, 10, 11 },
201 { 0, 4, 5, 12, 13, 14, 30, 31 },
202 { 0, 3, 2, 5, 6, 7, 8, 9 },
203 { 0, 3, 2, 3, 5, 8, 9 },
204 { 0, 5, 6, 8, 9, 14, 15 },
205 { 0, 5, 6, 8, 9, 14, 15 },
206 { 0, 3, 2, 3, 5, 8, 9 },
207 { 0, 3, 2, 3, 4, 5 },
210 static const uint8_t mv_syms[16][10] =
212 { 0, 8, 1, 2, 9, 3, 6, 7, 5, 4 },
213 { 9, 1, 2, 8, 0, 3, 5, 4 },
214 { 0, 1, 2, 9, 5, 4, 3, 8 },
215 { 1, 2, 0, 5, 4, 8, 3 },
216 { 8, 1, 2, 9, 0, 3, 5, 4 },
217 { 1, 3, 2, 9, 8, 0, 5, 4 },
218 { 1, 2, 0, 9, 8, 3, 5, 4 },
219 { 1, 2, 0, 8, 5, 4, 3 },
220 { 0, 1, 2, 8, 5, 4, 3, 9 },
221 { 1, 2, 0, 9, 8, 3, 5, 4 },
222 { 0, 1, 3, 2, 9, 8, 5, 4 },
223 { 0, 1, 4, 3, 2, 8, 5 },
224 { 1, 2, 0, 5, 4, 9, 3 },
225 { 1, 2, 0, 9, 5, 4, 3 },
226 { 0, 1, 5, 3, 2, 9, 4 },
227 { 0, 1, 4, 5, 3, 2 },
230 static const uint8_t mv_bits_mods[16][10] =
232 { 2, 2, 3, 3, 4, 4, 5, 5, 5, 5 },
233 { 2, 2, 3, 3, 4, 4, 4, 4 },
234 { 2, 2, 3, 3, 4, 4, 4, 4 },
235 { 1, 3, 3, 3, 4, 5, 5 },
236 { 2, 2, 3, 3, 4, 4, 4, 4 },
237 { 2, 2, 3, 3, 4, 4, 4, 4 },
238 { 2, 2, 3, 3, 4, 4, 4, 4 },
239 { 2, 2, 2, 3, 4, 5, 5 },
240 { 2, 2, 3, 3, 4, 4, 4, 4 },
241 { 2, 2, 3, 3, 4, 4, 4, 4 },
242 { 2, 2, 3, 3, 3, 4, 5, 5 },
243 { 2, 2, 3, 3, 3, 4, 4 },
244 { 1, 3, 3, 4, 4, 4, 4 },
245 { 2, 2, 3, 3, 3, 4, 4 },
246 { 2, 2, 3, 3, 3, 4, 4 },
247 { 2, 2, 3, 3, 3, 3 },
250 static const uint8_t mv_codes_mods[16][10] =
252 { 0, 3, 2, 3, 9, 10, 16, 17, 22, 23 },
253 { 0, 3, 2, 4, 6, 7, 10, 11 },
254 { 1, 3, 0, 5, 2, 3, 8, 9 },
255 { 0, 4, 6, 7, 10, 22, 23 },
256 { 0, 3, 3, 4, 4, 5, 10, 11 },
257 { 0, 3, 2, 5, 6, 7, 8, 9 },
258 { 0, 3, 2, 5, 6, 7, 8, 9 },
259 { 0, 1, 3, 4, 10, 22, 23 },
260 { 0, 3, 2, 4, 6, 7, 10, 11 },
261 { 0, 3, 3, 5, 4, 5, 8, 9 },
262 { 0, 3, 2, 3, 5, 9, 16, 17 },
263 { 0, 3, 2, 4, 5, 6, 7 },
264 { 0, 5, 6, 8, 9, 14, 15 },
265 { 0, 3, 2, 4, 5, 6, 7 },
266 { 0, 3, 2, 4, 5, 6, 7 },
267 { 1, 2, 0, 1, 6, 7 },
270 static const uint8_t mv_syms_mods[16][10] =
272 { 1, 0, 8, 9, 2, 7, 4, 3, 5, 6 },
273 { 0, 1, 9, 2, 5, 4, 3, 8 },
274 { 0, 1, 3, 2, 9, 5, 4, 8 },
275 { 1, 3, 2, 0, 4, 8, 5 },
276 { 0, 1, 8, 2, 5, 4, 3, 9 },
277 { 0, 1, 3, 2, 5, 9, 4, 8 },
278 { 0, 1, 3, 2, 9, 5, 8, 4 },
279 { 0, 2, 1, 3, 4, 8, 5 },
280 { 0, 1, 3, 2, 8, 4, 5, 9 },
281 { 2, 1, 3, 0, 8, 9, 5, 4 },
282 { 0, 1, 4, 3, 2, 5, 8, 9 },
283 { 0, 1, 4, 3, 2, 8, 5 },
284 { 1, 2, 0, 9, 4, 5, 3 },
285 { 2, 1, 4, 3, 0, 9, 5 },
286 { 0, 1, 4, 3, 2, 9, 5 },
287 { 1, 0, 5, 4, 3, 2 },
290 typedef struct BlockXY {
299 typedef struct MotionXY {
303 typedef struct MobiClipContext {
324 BswapDSPContext bdsp;
327 static av_cold int mobiclip_init(AVCodecContext *avctx)
329 MobiClipContext *s = avctx->priv_data;
332 if (avctx->width & 15 || avctx->height & 15) {
333 av_log(avctx, AV_LOG_ERROR, "width/height not multiple of 16\n");
334 return AVERROR_INVALIDDATA;
337 ff_bswapdsp_init(&s->bdsp);
339 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
341 ret = ff_init_vlc_sparse(&s->vlc[0], 12, 104,
342 bits0, sizeof(*bits0), sizeof(*bits0),
343 codes0, sizeof(*codes0), sizeof(*codes0),
344 syms0, sizeof(*syms0), sizeof(*syms0), 0);
348 ret = ff_init_vlc_sparse(&s->vlc[1], 12, 104,
349 bits0, sizeof(*bits0), sizeof(*bits0),
350 codes0, sizeof(*codes0), sizeof(*codes0),
351 syms1, sizeof(*syms1), sizeof(*syms1), 0);
355 s->motion = av_calloc(avctx->width / 16 + 3, sizeof(MotionXY));
357 return AVERROR(ENOMEM);
358 s->motion_size = (avctx->width / 16 + 3) * sizeof(MotionXY);
360 for (int i = 0; i < 6; i++) {
361 s->pic[i] = av_frame_alloc();
363 return AVERROR(ENOMEM);
366 for (int j = 0; j < 16; j++) {
367 ret = ff_init_vlc_sparse(&s->mv_vlc[0][j], 8, mv_len[j],
368 mv_bits_mods[j], sizeof(*mv_bits_mods[j]), sizeof(*mv_bits_mods[j]),
369 mv_codes_mods[j], sizeof(*mv_codes_mods[j]), sizeof(*mv_codes_mods[j]),
370 mv_syms_mods[j], sizeof(*mv_syms_mods[j]), sizeof(*mv_syms_mods[j]), 0);
374 ret = ff_init_vlc_sparse(&s->mv_vlc[1][j], 8, mv_len[j],
375 mv_bits[j], sizeof(*mv_bits[j]), sizeof(*mv_bits[j]),
376 mv_codes[j], sizeof(*mv_codes[j]), sizeof(*mv_codes[j]),
377 mv_syms[j], sizeof(*mv_syms[j]), sizeof(*mv_syms[j]), 0);
385 static int setup_qtables(AVCodecContext *avctx, int quantizer)
387 MobiClipContext *s = avctx->priv_data;
390 if (quantizer < 12 || quantizer > 161)
391 return AVERROR_INVALIDDATA;
393 s->quantizer = quantizer;
398 for (int i = 0; i < 16; i++)
399 s->qtab[0][i] = quant4x4_tab[qx][i] << qy;
401 for (int i = 0; i < 64; i++)
402 s->qtab[1][i] = quant8x8_tab[qx][i] << (qy - 2);
404 for (int i = 0; i < 20; i++)
410 static void inverse4(unsigned *rs)
412 unsigned a = rs[0] + rs[2];
413 unsigned b = rs[0] - rs[2];
414 unsigned c = rs[1] + ((int)rs[3] >> 1);
415 unsigned d = ((int)rs[1] >> 1) - rs[3];
423 static void idct(int *arr, int size)
426 unsigned x3, x2, x1, x0;
441 e = (unsigned)arr[7] + arr[1] - arr[3] - (arr[3] >> 1);
442 f = (unsigned)arr[7] - arr[1] + arr[5] + (arr[5] >> 1);
443 g = (unsigned)arr[5] - arr[3] - arr[7] - (arr[7] >> 1);
444 h = (unsigned)arr[5] + arr[3] + arr[1] + (arr[1] >> 1);
445 x3 = (unsigned)g + (h >> 2);
446 x2 = (unsigned)e + (f >> 2);
447 x1 = (e >> 2) - (unsigned)f;
448 x0 = (unsigned)h - (g >> 2);
450 arr[0] = tmp[0] + x0;
451 arr[1] = tmp[1] + x1;
452 arr[2] = tmp[2] + x2;
453 arr[3] = tmp[3] + x3;
454 arr[4] = tmp[3] - x3;
455 arr[5] = tmp[2] - x2;
456 arr[6] = tmp[1] - x1;
457 arr[7] = tmp[0] - x0;
460 static int read_run_encoding(AVCodecContext *avctx,
461 int *last, int *run, int *level)
463 MobiClipContext *s = avctx->priv_data;
464 GetBitContext *gb = &s->gb;
465 int n = get_vlc2(gb, s->vlc[s->dct_tab_idx].table,
466 s->vlc[s->dct_tab_idx].bits, 2);
469 return AVERROR_INVALIDDATA;
471 *last = (n >> 11) == 1;
472 *run = (n >> 5) & 0x3F;
478 static int add_coefficients(AVCodecContext *avctx, AVFrame *frame,
479 int bx, int by, int size, int plane)
481 MobiClipContext *s = avctx->priv_data;
482 GetBitContext *gb = &s->gb;
484 const uint8_t *ztab = size == 8 ? ff_zigzag_direct : zigzag4x4_tab;
485 const int *qtab = s->qtab[size == 8];
486 uint8_t *dst = frame->data[plane] + by * frame->linesize[plane] + bx;
489 for (int pos = 0; get_bits_left(gb) > 0; pos++) {
490 int qval, last, run, level;
492 ret = read_run_encoding(avctx, &last, &run, &level);
499 } else if (!get_bits1(gb)) {
500 ret = read_run_encoding(avctx, &last, &run, &level);
503 level += run_residue[s->dct_tab_idx][(last ? 64 : 0) + run];
506 } else if (!get_bits1(gb)) {
507 ret = read_run_encoding(avctx, &last, &run, &level);
510 run += run_residue[s->dct_tab_idx][128 + (last ? 64 : 0) + level];
514 last = get_bits1(gb);
515 run = get_bits(gb, 6);
516 level = get_sbits(gb, 12);
520 if (pos >= size * size)
521 return AVERROR_INVALIDDATA;
523 mat[ztab[pos]] = qval *(unsigned)level;
530 for (int y = 0; y < size; y++)
531 idct(&mat[y * size], size);
533 for (int y = 0; y < size; y++) {
534 for (int x = y + 1; x < size; x++) {
535 int a = mat[x * size + y];
536 int b = mat[y * size + x];
538 mat[y * size + x] = a;
539 mat[x * size + y] = b;
542 idct(&mat[y * size], size);
543 for (int x = 0; x < size; x++)
544 dst[x] = av_clip_uint8(dst[x] + (mat[y * size + x] >> 6));
545 dst += frame->linesize[plane];
551 static int add_pframe_coefficients(AVCodecContext *avctx, AVFrame *frame,
552 int bx, int by, int size, int plane)
554 MobiClipContext *s = avctx->priv_data;
555 GetBitContext *gb = &s->gb;
556 int ret, idx = get_ue_golomb(gb);
559 ret = add_coefficients(avctx, frame, bx, by, size, plane);
560 } else if (idx < FF_ARRAY_ELEMS(pframe_block4x4_coefficients_tab)) {
561 int flags = pframe_block4x4_coefficients_tab[idx];
563 for (int y = by; y < by + 8; y += 4) {
564 for (int x = bx; x < bx + 8; x += 4) {
566 ret = add_coefficients(avctx, frame, x, y, 4, plane);
574 ret = AVERROR_INVALIDDATA;
580 static int adjust(int x, int size)
582 return size == 16 ? (x + 1) >> 1 : x;
585 static uint8_t pget(BlockXY b)
590 if (b.x == -1 && b.y >= b.size) {
591 ret.x = -1, ret.y = b.size - 1;
592 } else if (b.x >= -1 && b.y >= -1) {
593 ret.x = b.x, ret.y = b.y;
594 } else if (b.x == -1 && b.y == -2) {
595 ret.x = 0, ret.y = -1;
596 } else if (b.x == -2 && b.y == -1) {
597 ret.x = -1, ret.y = 0;
600 y = av_clip(ret.ay + ret.y, 0, ret.h - 1);
601 x = av_clip(ret.ax + ret.x, 0, ret.w - 1);
603 return ret.block[y * ret.linesize + x];
606 static uint8_t half(int a, int b)
608 return ((a + b) + 1) / 2;
611 static uint8_t half3(int a, int b, int c)
613 return ((a + b + b + c) * 2 / 4 + 1) / 2;;
616 static uint8_t pick_above(BlockXY bxy)
623 static uint8_t pick_left(BlockXY bxy)
630 static uint8_t half_horz(BlockXY bxy)
632 BlockXY a = bxy, b = bxy, c = bxy;
637 return half3(pget(a), pget(b), pget(c));
640 static uint8_t half_vert(BlockXY bxy)
642 BlockXY a = bxy, b = bxy, c = bxy;
647 return half3(pget(a), pget(b), pget(c));
650 static uint8_t pick_4(BlockXY bxy)
654 if ((bxy.x % 2) == 0) {
660 ba.y = bxy.y + bxy.x / 2;
665 bb.y = bxy.y + bxy.x / 2 + 1;
674 ba.y = bxy.y + bxy.x / 2 + 1;
681 static uint8_t pick_5(BlockXY bxy)
694 val = half(pget(a), pget(b));
695 } else if (bxy.y == 0) {
702 } else if (bxy.x == 1) {
721 static uint8_t pick_6(BlockXY bxy)
734 val = half(pget(a), pget(b));
735 } else if (bxy.x == 0) {
742 } else if (bxy.y == 1) {
761 static uint8_t pick_7(BlockXY bxy)
790 return half3(acc1, clr, acc2);
793 static uint8_t pick_8(BlockXY bxy)
811 } else if (bxy.y == 1) {
816 } else if (bxy.x < bxy.size - 1) {
821 } else if (bxy.y % 2 == 0) {
824 ba.x = bxy.y / 2 + bxy.size - 1;
828 bb.x = bxy.y / 2 + bxy.size;
835 ba.x = bxy.y / 2 + bxy.size;
844 static void block_fill_simple(uint8_t *block, int size, int linesize, int fill)
846 for (int y = 0; y < size; y++) {
847 memset(block, fill, size);
852 static void block_fill(uint8_t *block, int size, int linesize,
853 int w, int h, int ax, int ay,
854 uint8_t (*pick)(BlockXY bxy))
860 bxy.linesize = linesize;
866 for (int y = 0; y < size; y++) {
868 for (int x = 0; x < size; x++) {
875 block[ax + x + (ay + y) * linesize] = val;
880 static int block_sum(const uint8_t *block, int w, int h, int linesize)
884 for (int y = 0; y < h; y++) {
885 for (int x = 0; x < w; x++) {
894 static int predict_intra(AVCodecContext *avctx, AVFrame *frame, int ax, int ay,
895 int pmode, int add_coeffs, int size, int plane)
897 MobiClipContext *s = avctx->priv_data;
898 GetBitContext *gb = &s->gb;
899 int w = avctx->width >> !!plane, h = avctx->height >> !!plane;
904 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_above);
907 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_left);
913 uint8_t *top = frame->data[plane] + FFMAX(ay - 1, 0) * frame->linesize[plane] + ax;
914 uint8_t *left = frame->data[plane] + ay * frame->linesize[plane] + FFMAX(ax - 1, 0);
915 int bottommost = frame->data[plane][(ay + size - 1) * frame->linesize[plane] + FFMAX(ax - 1, 0)];
916 int rightmost = frame->data[plane][FFMAX(ay - 1, 0) * frame->linesize[plane] + ax + size - 1];
917 int avg = (bottommost + rightmost + 1) / 2 + 2 * get_se_golomb(gb);
918 int r6 = adjust(avg - bottommost, size);
919 int r9 = adjust(avg - rightmost, size);
920 int shift = adjust(size, size) == 8 ? 3 : 2;
923 for (int x = 0; x < size; x++) {
925 arr1[x] = adjust(((bottommost - val) * (1 << shift)) + r6 * (x + 1), size);
928 for (int y = 0; y < size; y++) {
929 int val = left[y * frame->linesize[plane]];
930 arr2[y] = adjust(((rightmost - val) * (1 << shift)) + r9 * (y + 1), size);
933 block = frame->data[plane] + ay * frame->linesize[plane] + ax;
934 for (int y = 0; y < size; y++) {
935 for (int x = 0; x < size; x++) {
936 block[x] = (((top[x] + left[0] + ((arr1[x] * (y + 1) +
937 arr2[y] * (x + 1)) >> 2 * shift)) + 1) / 2) & 0xFF;
939 block += frame->linesize[plane];
940 left += frame->linesize[plane];
948 if (ax == 0 && ay == 0) {
950 } else if (ax >= 1 && ay >= 1) {
951 int left = block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1,
952 1, size, frame->linesize[plane]);
953 int top = block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax,
954 size, 1, frame->linesize[plane]);
956 fill = ((left + top) * 2 / (2 * size) + 1) / 2;
957 } else if (ax >= 1) {
958 fill = (block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1,
959 1, size, frame->linesize[plane]) * 2 / size + 1) / 2;
960 } else if (ay >= 1) {
961 fill = (block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax,
962 size, 1, frame->linesize[plane]) * 2 / size + 1) / 2;
967 block_fill_simple(frame->data[plane] + ay * frame->linesize[plane] + ax,
968 size, frame->linesize[plane], fill);
972 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_4);
975 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_5);
978 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_6);
981 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_7);
984 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_8);
989 ret = add_coefficients(avctx, frame, ax, ay, size, plane);
994 static int get_prediction(AVCodecContext *avctx, int x, int y, int size)
996 MobiClipContext *s = avctx->priv_data;
997 GetBitContext *gb = &s->gb;
998 int index = (y & 0xC) | (x / 4 % 4);
1000 uint8_t val = FFMIN(s->pre[index], index % 4 == 0 ? 9 : s->pre[index + 3]);
1004 if (!get_bits1(gb)) {
1005 int x = get_bits(gb, 3);
1006 val = x + (x >= val ? 1 : 0);
1009 s->pre[index + 4] = val;
1011 s->pre[index + 5] = s->pre[index + 8] = s->pre[index + 9] = val;
1016 static int process_block(AVCodecContext *avctx, AVFrame *frame,
1017 int x, int y, int pmode, int has_coeffs, int plane)
1019 MobiClipContext *s = avctx->priv_data;
1020 GetBitContext *gb = &s->gb;
1025 pmode = get_prediction(avctx, x, y, 8);
1026 return predict_intra(avctx, frame, x, y, pmode, 0, 8, plane);
1029 tmp = get_ue_golomb(gb);
1030 if (tmp < 0 || tmp > FF_ARRAY_ELEMS(block4x4_coefficients_tab))
1031 return AVERROR_INVALIDDATA;
1035 pmode = get_prediction(avctx, x, y, 8);
1036 ret = predict_intra(avctx, frame, x, y, pmode, 1, 8, plane);
1038 int flags = block4x4_coefficients_tab[tmp - 1];
1040 for (int by = y; by < y + 8; by += 4) {
1041 for (int bx = x; bx < x + 8; bx += 4) {
1042 int new_pmode = pmode;
1045 new_pmode = get_prediction(avctx, bx, by, 4);
1046 ret = predict_intra(avctx, frame, bx, by, new_pmode, flags & 1, 4, plane);
1057 static int decode_macroblock(AVCodecContext *avctx, AVFrame *frame,
1058 int x, int y, int predict)
1060 MobiClipContext *s = avctx->priv_data;
1061 GetBitContext *gb = &s->gb;
1062 int flags, pmode_uv, idx = get_ue_golomb(gb);
1065 if (idx < 0 || idx >= FF_ARRAY_ELEMS(block8x8_coefficients_tab))
1066 return AVERROR_INVALIDDATA;
1068 flags = block8x8_coefficients_tab[idx];
1071 ret = process_block(avctx, frame, x, y, -1, flags & 1, 0);
1075 ret = process_block(avctx, frame, x + 8, y, -1, flags & 1, 0);
1079 ret = process_block(avctx, frame, x, y + 8, -1, flags & 1, 0);
1083 ret = process_block(avctx, frame, x + 8, y + 8, -1, flags & 1, 0);
1088 int pmode = get_bits(gb, 3);
1091 ret = predict_intra(avctx, frame, x, y, pmode, 0, 16, 0);
1097 ret = process_block(avctx, frame, x, y, pmode, flags & 1, 0);
1101 ret = process_block(avctx, frame, x + 8, y, pmode, flags & 1, 0);
1105 ret = process_block(avctx, frame, x, y + 8, pmode, flags & 1, 0);
1109 ret = process_block(avctx, frame, x + 8, y + 8, pmode, flags & 1, 0);
1115 pmode_uv = get_bits(gb, 3);
1116 if (pmode_uv == 2) {
1117 ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 1 + !s->moflex);
1120 ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 2 - !s->moflex);
1126 ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 1 + !s->moflex);
1130 ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 2 - !s->moflex);
1137 static int get_index(int x)
1139 return x == 16 ? 0 : x == 8 ? 1 : x == 4 ? 2 : x == 2 ? 3 : 0;
1142 static int predict_motion(AVCodecContext *avctx,
1143 int width, int height, int index,
1144 int offsetm, int offsetx, int offsety)
1146 MobiClipContext *s = avctx->priv_data;
1147 MotionXY *motion = s->motion;
1148 GetBitContext *gb = &s->gb;
1149 int fheight = avctx->height;
1150 int fwidth = avctx->width;
1153 int sidx = -FFMAX(1, index) + s->current_pic;
1154 MotionXY mv = s->motion[0];
1160 mv.x = mv.x + get_se_golomb(gb);
1161 mv.y = mv.y + get_se_golomb(gb);
1164 motion[offsetm].x = mv.x;
1165 motion[offsetm].y = mv.y;
1167 for (int i = 0; i < 3; i++) {
1168 int method, src_linesize, dst_linesize;
1172 offsetx = offsetx >> 1;
1173 offsety = offsety >> 1;
1177 height = height >> 1;
1178 fwidth = fwidth >> 1;
1179 fheight = fheight >> 1;
1182 av_assert0(s->pic[sidx]);
1183 av_assert0(s->pic[s->current_pic]);
1184 av_assert0(s->pic[s->current_pic]->data[i]);
1185 if (!s->pic[sidx]->data[i])
1186 return AVERROR_INVALIDDATA;
1188 method = (mv.x & 1) | ((mv.y & 1) << 1);
1189 src_linesize = s->pic[sidx]->linesize[i];
1190 dst_linesize = s->pic[s->current_pic]->linesize[i];
1191 dst = s->pic[s->current_pic]->data[i] + offsetx + offsety * dst_linesize;
1193 if (offsetx + (mv.x >> 1) < 0 ||
1194 offsety + (mv.y >> 1) < 0 ||
1195 offsetx + width + (mv.x + 1 >> 1) > fwidth ||
1196 offsety + height + (mv.y + 1 >> 1) > fheight)
1197 return AVERROR_INVALIDDATA;
1201 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1202 (offsety + (mv.y >> 1)) * src_linesize;
1203 for (int y = 0; y < height; y++) {
1204 for (int x = 0; x < width; x++)
1206 dst += dst_linesize;
1207 src += src_linesize;
1211 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1212 (offsety + (mv.y >> 1)) * src_linesize;
1213 for (int y = 0; y < height; y++) {
1214 for (int x = 0; x < width; x++) {
1215 dst[x] = (uint8_t)((src[x] >> 1) + (src[x + 1] >> 1));
1218 dst += dst_linesize;
1219 src += src_linesize;
1223 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1224 (offsety + (mv.y >> 1)) * src_linesize;
1225 for (int y = 0; y < height; y++) {
1226 for (int x = 0; x < width; x++) {
1227 dst[x] = (uint8_t)((src[x] >> 1) + (src[x + src_linesize] >> 1));
1230 dst += dst_linesize;
1231 src += src_linesize;
1235 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1236 (offsety + (mv.y >> 1)) * src_linesize;
1237 for (int y = 0; y < height; y++) {
1238 for (int x = 0; x < width; x++) {
1239 dst[x] = (uint8_t)((((src[x] >> 1) + (src[x + 1] >> 1)) >> 1) +
1240 (((src[x + src_linesize] >> 1) + (src[x + 1 + src_linesize] >> 1)) >> 1));
1243 dst += dst_linesize;
1244 src += src_linesize;
1251 int adjx = index == 8 ? 0 : width / 2;
1252 int adjy = index == 8 ? height / 2 : 0;
1254 width = width - adjx;
1255 height = height - adjy;
1256 tidx = get_index(height) * 4 + get_index(width);
1258 for (int i = 0; i < 2; i++) {
1261 idx2 = get_vlc2(gb, s->mv_vlc[s->moflex][tidx].table,
1262 s->mv_vlc[s->moflex][tidx].bits, 1);
1264 return AVERROR_INVALIDDATA;
1266 ret = predict_motion(avctx, width, height, idx2,
1267 offsetm, offsetx + i * adjx, offsety + i * adjy);
1276 static int mobiclip_decode(AVCodecContext *avctx, void *data,
1277 int *got_frame, AVPacket *pkt)
1279 MobiClipContext *s = avctx->priv_data;
1280 GetBitContext *gb = &s->gb;
1281 AVFrame *frame = s->pic[s->current_pic];
1284 av_fast_padded_malloc(&s->bitstream, &s->bitstream_size,
1287 if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0)
1290 s->bdsp.bswap16_buf((uint16_t *)s->bitstream,
1291 (uint16_t *)pkt->data,
1292 (pkt->size + 1) >> 1);
1294 ret = init_get_bits8(gb, s->bitstream, FFALIGN(pkt->size, 2));
1298 if (get_bits1(gb)) {
1299 frame->pict_type = AV_PICTURE_TYPE_I;
1300 frame->key_frame = 1;
1301 s->moflex = get_bits1(gb);
1302 s->dct_tab_idx = get_bits1(gb);
1304 ret = setup_qtables(avctx, get_bits(gb, 6));
1308 for (int y = 0; y < avctx->height; y += 16) {
1309 for (int x = 0; x < avctx->width; x += 16) {
1310 ret = decode_macroblock(avctx, frame, x, y, get_bits1(gb));
1316 MotionXY *motion = s->motion;
1318 memset(motion, 0, s->motion_size);
1320 frame->pict_type = AV_PICTURE_TYPE_P;
1321 frame->key_frame = 0;
1324 ret = setup_qtables(avctx, s->quantizer + get_se_golomb(gb));
1328 for (int y = 0; y < avctx->height; y += 16) {
1329 for (int x = 0; x < avctx->width; x += 16) {
1332 motion[0].x = mid_pred(motion[x / 16 + 1].x, motion[x / 16 + 2].x, motion[x / 16 + 3].x);
1333 motion[0].y = mid_pred(motion[x / 16 + 1].y, motion[x / 16 + 2].y, motion[x / 16 + 3].y);
1334 motion[x / 16 + 2].x = 0;
1335 motion[x / 16 + 2].y = 0;
1337 idx = get_vlc2(gb, s->mv_vlc[s->moflex][0].table,
1338 s->mv_vlc[s->moflex][0].bits, 1);
1340 return AVERROR_INVALIDDATA;
1342 if (idx == 6 || idx == 7) {
1343 ret = decode_macroblock(avctx, frame, x, y, idx == 7);
1348 ret = predict_motion(avctx, 16, 16, idx, x / 16 + 2, x, y);
1351 idx2 = get_ue_golomb(gb);
1352 if (idx2 >= FF_ARRAY_ELEMS(pframe_block8x8_coefficients_tab))
1353 return AVERROR_INVALIDDATA;
1354 flags = pframe_block8x8_coefficients_tab[idx2];
1356 for (int sy = y; sy < y + 16; sy += 8) {
1357 for (int sx = x; sx < x + 16; sx += 8) {
1359 add_pframe_coefficients(avctx, frame, sx, sy, 8, 0);
1365 add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 1 + !s->moflex);
1368 add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 2 - !s->moflex);
1375 avctx->colorspace = AVCOL_SPC_YCGCO;
1377 s->current_pic = (s->current_pic + 1) % 6;
1378 ret = av_frame_ref(data, frame);
1386 static void mobiclip_flush(AVCodecContext *avctx)
1388 MobiClipContext *s = avctx->priv_data;
1390 for (int i = 0; i < 6; i++)
1391 av_frame_unref(s->pic[i]);
1394 static av_cold int mobiclip_close(AVCodecContext *avctx)
1396 MobiClipContext *s = avctx->priv_data;
1398 ff_free_vlc(&s->vlc[0]);
1399 ff_free_vlc(&s->vlc[1]);
1401 for (int i = 0; i < 16; i++) {
1402 ff_free_vlc(&s->mv_vlc[0][i]);
1403 ff_free_vlc(&s->mv_vlc[1][i]);
1406 av_freep(&s->bitstream);
1407 s->bitstream_size = 0;
1408 av_freep(&s->motion);
1411 for (int i = 0; i < 6; i++) {
1412 av_frame_free(&s->pic[i]);
1418 AVCodec ff_mobiclip_decoder = {
1420 .long_name = NULL_IF_CONFIG_SMALL("MobiClip Video"),
1421 .type = AVMEDIA_TYPE_VIDEO,
1422 .id = AV_CODEC_ID_MOBICLIP,
1423 .priv_data_size = sizeof(MobiClipContext),
1424 .init = mobiclip_init,
1425 .decode = mobiclip_decode,
1426 .flush = mobiclip_flush,
1427 .close = mobiclip_close,
1428 .capabilities = AV_CODEC_CAP_DR1,
1429 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,