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_RL_VLC_BITS 12
35 #define MOBI_MV_VLC_BITS 6
37 static const uint8_t zigzag4x4_tab[] =
39 0x00, 0x04, 0x01, 0x02, 0x05, 0x08, 0x0C, 0x09, 0x06, 0x03, 0x07, 0x0A,
40 0x0D, 0x0E, 0x0B, 0x0F
43 static const uint8_t quant4x4_tab[][16] =
45 { 10, 13, 13, 10, 16, 10, 13, 13, 13, 13, 16, 10, 16, 13, 13, 16 },
46 { 11, 14, 14, 11, 18, 11, 14, 14, 14, 14, 18, 11, 18, 14, 14, 18 },
47 { 13, 16, 16, 13, 20, 13, 16, 16, 16, 16, 20, 13, 20, 16, 16, 20 },
48 { 14, 18, 18, 14, 23, 14, 18, 18, 18, 18, 23, 14, 23, 18, 18, 23 },
49 { 16, 20, 20, 16, 25, 16, 20, 20, 20, 20, 25, 16, 25, 20, 20, 25 },
50 { 18, 23, 23, 18, 29, 18, 23, 23, 23, 23, 29, 18, 29, 23, 23, 29 },
53 static const uint8_t quant8x8_tab[][64] =
55 { 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,
56 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,},
57 { 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,
58 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,},
59 { 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,
60 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,},
61 { 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,
62 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,},
63 { 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,
64 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,},
65 { 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,
66 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,},
69 static const uint8_t block4x4_coefficients_tab[] =
71 15, 0, 2, 1, 4, 8, 12, 3, 11, 13, 14, 7, 10, 5, 9, 6,
74 static const uint8_t pframe_block4x4_coefficients_tab[] =
76 0, 4, 1, 8, 2, 12, 3, 5, 10, 15, 7, 13, 14, 11, 9, 6,
79 static const uint8_t block8x8_coefficients_tab[] =
81 0x00, 0x1F, 0x3F, 0x0F, 0x08, 0x04, 0x02, 0x01, 0x0B, 0x0E, 0x1B, 0x0D,
82 0x03, 0x07, 0x0C, 0x17, 0x1D, 0x0A, 0x1E, 0x05, 0x10, 0x2F, 0x37, 0x3B,
83 0x13, 0x3D, 0x3E, 0x09, 0x1C, 0x06, 0x15, 0x1A, 0x33, 0x11, 0x12, 0x14,
84 0x18, 0x20, 0x3C, 0x35, 0x19, 0x16, 0x3A, 0x30, 0x31, 0x32, 0x27, 0x34,
85 0x2B, 0x2D, 0x39, 0x38, 0x23, 0x36, 0x2E, 0x21, 0x25, 0x22, 0x24, 0x2C,
86 0x2A, 0x28, 0x29, 0x26,
89 static const uint8_t pframe_block8x8_coefficients_tab[] =
91 0x00, 0x0F, 0x04, 0x01, 0x08, 0x02, 0x0C, 0x03, 0x05, 0x0A, 0x0D, 0x07, 0x0E, 0x0B, 0x1F, 0x09,
92 0x06, 0x10, 0x3F, 0x1E, 0x17, 0x1D, 0x1B, 0x1C, 0x13, 0x18, 0x1A, 0x12, 0x11, 0x14, 0x15, 0x20,
93 0x2F, 0x16, 0x19, 0x37, 0x3D, 0x3E, 0x3B, 0x3C, 0x33, 0x35, 0x21, 0x24, 0x22, 0x28, 0x23, 0x2C,
94 0x30, 0x27, 0x2D, 0x25, 0x3A, 0x2B, 0x2E, 0x2A, 0x31, 0x34, 0x38, 0x32, 0x29, 0x26, 0x39, 0x36
97 static const uint8_t run_residue[2][256] =
100 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,
101 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,
102 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,
103 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,
104 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,
105 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,
106 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,
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,
110 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,
111 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,
112 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,
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 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,
115 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,
116 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,
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,
121 static const uint8_t bits0[] = {
122 9, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
123 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12,
124 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 10, 10, 9,
125 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
126 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
127 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6,
128 6, 6, 6, 6, 6, 6, 5, 5, 5, 4, 2, 3, 4, 4,
131 static const uint16_t codes0[] = {
132 0x0, 0x4, 0x5, 0x6, 0x7, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
133 0xB, 0xC, 0xD, 0xE, 0xF, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
134 0x26, 0x27, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
135 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x3, 0x20,
136 0x21, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
137 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23,
138 0x24, 0x25, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
139 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x10, 0x11, 0x12, 0x13, 0x14,
140 0x15, 0x16, 0x17, 0xC, 0xD, 0xE, 0xF, 0x10, 0x11, 0x12,
141 0x13, 0x14, 0x15, 0xB, 0xC, 0xD, 0x7, 0x2, 0x6, 0xE, 0xF,
144 static const uint16_t syms0[] = {
145 0x0, 0x822, 0x803, 0xB, 0xA, 0xB81, 0xB61, 0xB41, 0xB21, 0x122,
146 0x102, 0xE2, 0xC2, 0xA2, 0x63, 0x43, 0x24, 0xC, 0x25, 0x2E1, 0x301,
147 0xBA1, 0xBC1, 0xBE1, 0xC01, 0x26, 0x44, 0x83, 0xA3, 0xC3, 0x142,
148 0x321, 0x341, 0xC21, 0xC41, 0xC61, 0xC81, 0xCA1, 0xCC1, 0xCE1, 0xD01,
149 0x0, 0x9, 0x8, 0xB01, 0xAE1, 0xAC1, 0xAA1, 0xA81, 0xA61, 0xA41, 0xA21,
150 0x802, 0x2C1, 0x2A1, 0x281, 0x261, 0x241, 0x221, 0x201, 0x1E1, 0x82,
151 0x62, 0x7, 0x6, 0xA01, 0x9E1, 0x9C1, 0x9A1, 0x981, 0x961, 0x941, 0x921,
152 0x1C1, 0x1A1, 0x42, 0x23, 0x5, 0x901, 0x8E1, 0x8C1, 0x8A1, 0x181, 0x161,
153 0x141, 0x4, 0x881, 0x861, 0x841, 0x821, 0x121, 0x101, 0xE1, 0xC1, 0x22,
154 0x3, 0xA1, 0x81, 0x61, 0x801, 0x1, 0x21, 0x41, 0x2,
157 static const uint16_t syms1[] = {
158 0x0, 0x807, 0x806, 0x16, 0x15, 0x842, 0x823, 0x805, 0x1A1, 0xA3, 0x102, 0x83,
159 0x64, 0x44, 0x27, 0x14, 0x13, 0x17, 0x18, 0x28, 0x122, 0x862, 0x882, 0x9E1, 0xA01,
160 0x19, 0x1A, 0x1B, 0x29, 0xC3, 0x2A, 0x45, 0xE3, 0x1C1, 0x808, 0x8A2, 0x8C2, 0xA21,
161 0xA41, 0xA61, 0xA81, 0x0, 0x12, 0x11, 0x9C1, 0x9A1, 0x981, 0x961, 0x941, 0x822, 0x804,
162 0x181, 0x161, 0xE2, 0xC2, 0xA2, 0x63, 0x43, 0x26, 0x25, 0x10, 0x82, 0xF, 0xE, 0xD, 0x901,
163 0x8E1, 0x8C1, 0x803, 0x141, 0x121, 0x101, 0x921, 0x62, 0x24, 0xC, 0xB, 0xA, 0x881, 0x861,
164 0xC1, 0x8A1, 0xE1, 0x42, 0x23, 0x9, 0x802, 0xA1, 0x841, 0x821, 0x81, 0x61, 0x8, 0x7, 0x22,
165 0x6, 0x41, 0x5, 0x4, 0x801, 0x1, 0x2, 0x21, 0x3,
168 static const uint8_t mv_len[16] =
170 10, 8, 8, 7, 8, 8, 8, 7, 8, 8, 8, 7, 7, 7, 7, 6,
173 static const uint8_t mv_bits[16][10] =
175 { 1, 3, 3, 4, 4, 5, 5, 5, 6, 6 },
176 { 2, 2, 3, 3, 3, 4, 5, 5 },
177 { 2, 2, 3, 3, 4, 4, 4, 4 },
178 { 1, 3, 3, 4, 4, 4, 4 },
179 { 2, 2, 3, 3, 3, 4, 5, 5 },
180 { 2, 3, 3, 3, 3, 3, 4, 4 },
181 { 1, 3, 3, 4, 4, 4, 5, 5 },
182 { 1, 3, 3, 4, 4, 4, 4 },
183 { 2, 2, 3, 3, 4, 4, 4, 4 },
184 { 1, 3, 3, 4, 4, 4, 5, 5 },
185 { 2, 2, 3, 3, 4, 4, 4, 4 },
186 { 2, 2, 3, 3, 3, 4, 4 },
187 { 1, 3, 3, 4, 4, 4, 4 },
188 { 1, 3, 3, 4, 4, 4, 4 },
189 { 2, 2, 3, 3, 3, 4, 4 },
190 { 2, 2, 3, 3, 3, 3 },
193 static const uint8_t mv_codes[16][10] =
195 { 1, 0, 2, 2, 7, 6, 7, 12, 26, 27 },
196 { 0, 2, 2, 6, 7, 6, 14, 15 },
197 { 0, 3, 3, 4, 4, 5, 10, 11 },
198 { 0, 5, 7, 8, 9, 12, 13 },
199 { 1, 3, 0, 1, 5, 8, 18, 19 },
200 { 3, 0, 2, 3, 4, 5, 2, 3 },
201 { 0, 4, 5, 12, 13, 14, 30, 31 },
202 { 0, 5, 6, 8, 9, 14, 15 },
203 { 0, 3, 3, 4, 4, 5, 10, 11 },
204 { 0, 4, 5, 12, 13, 14, 30, 31 },
205 { 0, 3, 2, 5, 6, 7, 8, 9 },
206 { 0, 3, 2, 3, 5, 8, 9 },
207 { 0, 5, 6, 8, 9, 14, 15 },
208 { 0, 5, 6, 8, 9, 14, 15 },
209 { 0, 3, 2, 3, 5, 8, 9 },
210 { 0, 3, 2, 3, 4, 5 },
213 static const uint8_t mv_syms[16][10] =
215 { 0, 8, 1, 2, 9, 3, 6, 7, 5, 4 },
216 { 9, 1, 2, 8, 0, 3, 5, 4 },
217 { 0, 1, 2, 9, 5, 4, 3, 8 },
218 { 1, 2, 0, 5, 4, 8, 3 },
219 { 8, 1, 2, 9, 0, 3, 5, 4 },
220 { 1, 3, 2, 9, 8, 0, 5, 4 },
221 { 1, 2, 0, 9, 8, 3, 5, 4 },
222 { 1, 2, 0, 8, 5, 4, 3 },
223 { 0, 1, 2, 8, 5, 4, 3, 9 },
224 { 1, 2, 0, 9, 8, 3, 5, 4 },
225 { 0, 1, 3, 2, 9, 8, 5, 4 },
226 { 0, 1, 4, 3, 2, 8, 5 },
227 { 1, 2, 0, 5, 4, 9, 3 },
228 { 1, 2, 0, 9, 5, 4, 3 },
229 { 0, 1, 5, 3, 2, 9, 4 },
230 { 0, 1, 4, 5, 3, 2 },
233 static const uint8_t mv_bits_mods[16][10] =
235 { 2, 2, 3, 3, 4, 4, 5, 5, 5, 5 },
236 { 2, 2, 3, 3, 4, 4, 4, 4 },
237 { 2, 2, 3, 3, 4, 4, 4, 4 },
238 { 1, 3, 3, 3, 4, 5, 5 },
239 { 2, 2, 3, 3, 4, 4, 4, 4 },
240 { 2, 2, 3, 3, 4, 4, 4, 4 },
241 { 2, 2, 3, 3, 4, 4, 4, 4 },
242 { 2, 2, 2, 3, 4, 5, 5 },
243 { 2, 2, 3, 3, 4, 4, 4, 4 },
244 { 2, 2, 3, 3, 4, 4, 4, 4 },
245 { 2, 2, 3, 3, 3, 4, 5, 5 },
246 { 2, 2, 3, 3, 3, 4, 4 },
247 { 1, 3, 3, 4, 4, 4, 4 },
248 { 2, 2, 3, 3, 3, 4, 4 },
249 { 2, 2, 3, 3, 3, 4, 4 },
250 { 2, 2, 3, 3, 3, 3 },
253 static const uint8_t mv_codes_mods[16][10] =
255 { 0, 3, 2, 3, 9, 10, 16, 17, 22, 23 },
256 { 0, 3, 2, 4, 6, 7, 10, 11 },
257 { 1, 3, 0, 5, 2, 3, 8, 9 },
258 { 0, 4, 6, 7, 10, 22, 23 },
259 { 0, 3, 3, 4, 4, 5, 10, 11 },
260 { 0, 3, 2, 5, 6, 7, 8, 9 },
261 { 0, 3, 2, 5, 6, 7, 8, 9 },
262 { 0, 1, 3, 4, 10, 22, 23 },
263 { 0, 3, 2, 4, 6, 7, 10, 11 },
264 { 0, 3, 3, 5, 4, 5, 8, 9 },
265 { 0, 3, 2, 3, 5, 9, 16, 17 },
266 { 0, 3, 2, 4, 5, 6, 7 },
267 { 0, 5, 6, 8, 9, 14, 15 },
268 { 0, 3, 2, 4, 5, 6, 7 },
269 { 0, 3, 2, 4, 5, 6, 7 },
270 { 1, 2, 0, 1, 6, 7 },
273 static const uint8_t mv_syms_mods[16][10] =
275 { 1, 0, 8, 9, 2, 7, 4, 3, 5, 6 },
276 { 0, 1, 9, 2, 5, 4, 3, 8 },
277 { 0, 1, 3, 2, 9, 5, 4, 8 },
278 { 1, 3, 2, 0, 4, 8, 5 },
279 { 0, 1, 8, 2, 5, 4, 3, 9 },
280 { 0, 1, 3, 2, 5, 9, 4, 8 },
281 { 0, 1, 3, 2, 9, 5, 8, 4 },
282 { 0, 2, 1, 3, 4, 8, 5 },
283 { 0, 1, 3, 2, 8, 4, 5, 9 },
284 { 2, 1, 3, 0, 8, 9, 5, 4 },
285 { 0, 1, 4, 3, 2, 5, 8, 9 },
286 { 0, 1, 4, 3, 2, 8, 5 },
287 { 1, 2, 0, 9, 4, 5, 3 },
288 { 2, 1, 4, 3, 0, 9, 5 },
289 { 0, 1, 4, 3, 2, 9, 5 },
290 { 1, 0, 5, 4, 3, 2 },
293 typedef struct BlockXY {
302 typedef struct MotionXY {
306 typedef struct MobiClipContext {
327 BswapDSPContext bdsp;
330 static av_cold int mobiclip_init(AVCodecContext *avctx)
332 MobiClipContext *s = avctx->priv_data;
335 if (avctx->width & 15 || avctx->height & 15) {
336 av_log(avctx, AV_LOG_ERROR, "width/height not multiple of 16\n");
337 return AVERROR_INVALIDDATA;
340 ff_bswapdsp_init(&s->bdsp);
342 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
344 ret = ff_init_vlc_sparse(&s->vlc[0], MOBI_RL_VLC_BITS, 104,
345 bits0, sizeof(*bits0), sizeof(*bits0),
346 codes0, sizeof(*codes0), sizeof(*codes0),
347 syms0, sizeof(*syms0), sizeof(*syms0), 0);
351 ret = ff_init_vlc_sparse(&s->vlc[1], MOBI_RL_VLC_BITS, 104,
352 bits0, sizeof(*bits0), sizeof(*bits0),
353 codes0, sizeof(*codes0), sizeof(*codes0),
354 syms1, sizeof(*syms1), sizeof(*syms1), 0);
358 s->motion = av_calloc(avctx->width / 16 + 3, sizeof(MotionXY));
360 return AVERROR(ENOMEM);
361 s->motion_size = (avctx->width / 16 + 3) * sizeof(MotionXY);
363 for (int i = 0; i < 6; i++) {
364 s->pic[i] = av_frame_alloc();
366 return AVERROR(ENOMEM);
369 for (int j = 0; j < 16; j++) {
370 ret = ff_init_vlc_sparse(&s->mv_vlc[0][j], MOBI_MV_VLC_BITS, mv_len[j],
371 mv_bits_mods[j], sizeof(*mv_bits_mods[j]), sizeof(*mv_bits_mods[j]),
372 mv_codes_mods[j], sizeof(*mv_codes_mods[j]), sizeof(*mv_codes_mods[j]),
373 mv_syms_mods[j], sizeof(*mv_syms_mods[j]), sizeof(*mv_syms_mods[j]), 0);
377 ret = ff_init_vlc_sparse(&s->mv_vlc[1][j], MOBI_MV_VLC_BITS, mv_len[j],
378 mv_bits[j], sizeof(*mv_bits[j]), sizeof(*mv_bits[j]),
379 mv_codes[j], sizeof(*mv_codes[j]), sizeof(*mv_codes[j]),
380 mv_syms[j], sizeof(*mv_syms[j]), sizeof(*mv_syms[j]), 0);
388 static int setup_qtables(AVCodecContext *avctx, int quantizer)
390 MobiClipContext *s = avctx->priv_data;
393 if (quantizer < 12 || quantizer > 161)
394 return AVERROR_INVALIDDATA;
396 s->quantizer = quantizer;
401 for (int i = 0; i < 16; i++)
402 s->qtab[0][i] = quant4x4_tab[qx][i] << qy;
404 for (int i = 0; i < 64; i++)
405 s->qtab[1][i] = quant8x8_tab[qx][i] << (qy - 2);
407 for (int i = 0; i < 20; i++)
413 static void inverse4(unsigned *rs)
415 unsigned a = rs[0] + rs[2];
416 unsigned b = rs[0] - rs[2];
417 unsigned c = rs[1] + ((int)rs[3] >> 1);
418 unsigned d = ((int)rs[1] >> 1) - rs[3];
426 static void idct(int *arr, int size)
429 unsigned x3, x2, x1, x0;
444 e = (unsigned)arr[7] + arr[1] - arr[3] - (arr[3] >> 1);
445 f = (unsigned)arr[7] - arr[1] + arr[5] + (arr[5] >> 1);
446 g = (unsigned)arr[5] - arr[3] - arr[7] - (arr[7] >> 1);
447 h = (unsigned)arr[5] + arr[3] + arr[1] + (arr[1] >> 1);
448 x3 = (unsigned)g + (h >> 2);
449 x2 = (unsigned)e + (f >> 2);
450 x1 = (e >> 2) - (unsigned)f;
451 x0 = (unsigned)h - (g >> 2);
453 arr[0] = tmp[0] + x0;
454 arr[1] = tmp[1] + x1;
455 arr[2] = tmp[2] + x2;
456 arr[3] = tmp[3] + x3;
457 arr[4] = tmp[3] - x3;
458 arr[5] = tmp[2] - x2;
459 arr[6] = tmp[1] - x1;
460 arr[7] = tmp[0] - x0;
463 static void read_run_encoding(AVCodecContext *avctx,
464 int *last, int *run, int *level)
466 MobiClipContext *s = avctx->priv_data;
467 GetBitContext *gb = &s->gb;
468 int n = get_vlc2(gb, s->vlc[s->dct_tab_idx].table,
469 MOBI_RL_VLC_BITS, 1);
471 *last = (n >> 11) == 1;
472 *run = (n >> 5) & 0x3F;
476 static int add_coefficients(AVCodecContext *avctx, AVFrame *frame,
477 int bx, int by, int size, int plane)
479 MobiClipContext *s = avctx->priv_data;
480 GetBitContext *gb = &s->gb;
482 const uint8_t *ztab = size == 8 ? ff_zigzag_direct : zigzag4x4_tab;
483 const int *qtab = s->qtab[size == 8];
484 uint8_t *dst = frame->data[plane] + by * frame->linesize[plane] + bx;
486 for (int pos = 0; get_bits_left(gb) > 0; pos++) {
487 int qval, last, run, level;
489 read_run_encoding(avctx, &last, &run, &level);
494 } else if (!get_bits1(gb)) {
495 read_run_encoding(avctx, &last, &run, &level);
496 level += run_residue[s->dct_tab_idx][(last ? 64 : 0) + run];
499 } else if (!get_bits1(gb)) {
500 read_run_encoding(avctx, &last, &run, &level);
501 run += run_residue[s->dct_tab_idx][128 + (last ? 64 : 0) + level];
505 last = get_bits1(gb);
506 run = get_bits(gb, 6);
507 level = get_sbits(gb, 12);
511 if (pos >= size * size)
512 return AVERROR_INVALIDDATA;
514 mat[ztab[pos]] = qval *(unsigned)level;
521 for (int y = 0; y < size; y++)
522 idct(&mat[y * size], size);
524 for (int y = 0; y < size; y++) {
525 for (int x = y + 1; x < size; x++) {
526 int a = mat[x * size + y];
527 int b = mat[y * size + x];
529 mat[y * size + x] = a;
530 mat[x * size + y] = b;
533 idct(&mat[y * size], size);
534 for (int x = 0; x < size; x++)
535 dst[x] = av_clip_uint8(dst[x] + (mat[y * size + x] >> 6));
536 dst += frame->linesize[plane];
542 static int add_pframe_coefficients(AVCodecContext *avctx, AVFrame *frame,
543 int bx, int by, int size, int plane)
545 MobiClipContext *s = avctx->priv_data;
546 GetBitContext *gb = &s->gb;
547 int ret, idx = get_ue_golomb(gb);
550 ret = add_coefficients(avctx, frame, bx, by, size, plane);
551 } else if (idx < FF_ARRAY_ELEMS(pframe_block4x4_coefficients_tab)) {
552 int flags = pframe_block4x4_coefficients_tab[idx];
554 for (int y = by; y < by + 8; y += 4) {
555 for (int x = bx; x < bx + 8; x += 4) {
557 ret = add_coefficients(avctx, frame, x, y, 4, plane);
565 ret = AVERROR_INVALIDDATA;
571 static int adjust(int x, int size)
573 return size == 16 ? (x + 1) >> 1 : x;
576 static uint8_t pget(BlockXY b)
581 if (b.x == -1 && b.y >= b.size) {
582 ret.x = -1, ret.y = b.size - 1;
583 } else if (b.x >= -1 && b.y >= -1) {
584 ret.x = b.x, ret.y = b.y;
585 } else if (b.x == -1 && b.y == -2) {
586 ret.x = 0, ret.y = -1;
587 } else if (b.x == -2 && b.y == -1) {
588 ret.x = -1, ret.y = 0;
591 y = av_clip(ret.ay + ret.y, 0, ret.h - 1);
592 x = av_clip(ret.ax + ret.x, 0, ret.w - 1);
594 return ret.block[y * ret.linesize + x];
597 static uint8_t half(int a, int b)
599 return ((a + b) + 1) / 2;
602 static uint8_t half3(int a, int b, int c)
604 return ((a + b + b + c) * 2 / 4 + 1) / 2;;
607 static uint8_t pick_above(BlockXY bxy)
614 static uint8_t pick_left(BlockXY bxy)
621 static uint8_t half_horz(BlockXY bxy)
623 BlockXY a = bxy, b = bxy, c = bxy;
628 return half3(pget(a), pget(b), pget(c));
631 static uint8_t half_vert(BlockXY bxy)
633 BlockXY a = bxy, b = bxy, c = bxy;
638 return half3(pget(a), pget(b), pget(c));
641 static uint8_t pick_4(BlockXY bxy)
645 if ((bxy.x % 2) == 0) {
651 ba.y = bxy.y + bxy.x / 2;
656 bb.y = bxy.y + bxy.x / 2 + 1;
665 ba.y = bxy.y + bxy.x / 2 + 1;
672 static uint8_t pick_5(BlockXY bxy)
685 val = half(pget(a), pget(b));
686 } else if (bxy.y == 0) {
693 } else if (bxy.x == 1) {
712 static uint8_t pick_6(BlockXY bxy)
725 val = half(pget(a), pget(b));
726 } else if (bxy.x == 0) {
733 } else if (bxy.y == 1) {
752 static uint8_t pick_7(BlockXY bxy)
781 return half3(acc1, clr, acc2);
784 static uint8_t pick_8(BlockXY bxy)
802 } else if (bxy.y == 1) {
807 } else if (bxy.x < bxy.size - 1) {
812 } else if (bxy.y % 2 == 0) {
815 ba.x = bxy.y / 2 + bxy.size - 1;
819 bb.x = bxy.y / 2 + bxy.size;
826 ba.x = bxy.y / 2 + bxy.size;
835 static void block_fill_simple(uint8_t *block, int size, int linesize, int fill)
837 for (int y = 0; y < size; y++) {
838 memset(block, fill, size);
843 static void block_fill(uint8_t *block, int size, int linesize,
844 int w, int h, int ax, int ay,
845 uint8_t (*pick)(BlockXY bxy))
851 bxy.linesize = linesize;
857 for (int y = 0; y < size; y++) {
859 for (int x = 0; x < size; x++) {
866 block[ax + x + (ay + y) * linesize] = val;
871 static int block_sum(const uint8_t *block, int w, int h, int linesize)
875 for (int y = 0; y < h; y++) {
876 for (int x = 0; x < w; x++) {
885 static int predict_intra(AVCodecContext *avctx, AVFrame *frame, int ax, int ay,
886 int pmode, int add_coeffs, int size, int plane)
888 MobiClipContext *s = avctx->priv_data;
889 GetBitContext *gb = &s->gb;
890 int w = avctx->width >> !!plane, h = avctx->height >> !!plane;
895 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_above);
898 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_left);
904 uint8_t *top = frame->data[plane] + FFMAX(ay - 1, 0) * frame->linesize[plane] + ax;
905 uint8_t *left = frame->data[plane] + ay * frame->linesize[plane] + FFMAX(ax - 1, 0);
906 int bottommost = frame->data[plane][(ay + size - 1) * frame->linesize[plane] + FFMAX(ax - 1, 0)];
907 int rightmost = frame->data[plane][FFMAX(ay - 1, 0) * frame->linesize[plane] + ax + size - 1];
908 int avg = (bottommost + rightmost + 1) / 2 + 2 * get_se_golomb(gb);
909 int r6 = adjust(avg - bottommost, size);
910 int r9 = adjust(avg - rightmost, size);
911 int shift = adjust(size, size) == 8 ? 3 : 2;
914 for (int x = 0; x < size; x++) {
916 arr1[x] = adjust(((bottommost - val) * (1 << shift)) + r6 * (x + 1), size);
919 for (int y = 0; y < size; y++) {
920 int val = left[y * frame->linesize[plane]];
921 arr2[y] = adjust(((rightmost - val) * (1 << shift)) + r9 * (y + 1), size);
924 block = frame->data[plane] + ay * frame->linesize[plane] + ax;
925 for (int y = 0; y < size; y++) {
926 for (int x = 0; x < size; x++) {
927 block[x] = (((top[x] + left[0] + ((arr1[x] * (y + 1) +
928 arr2[y] * (x + 1)) >> 2 * shift)) + 1) / 2) & 0xFF;
930 block += frame->linesize[plane];
931 left += frame->linesize[plane];
939 if (ax == 0 && ay == 0) {
941 } else if (ax >= 1 && ay >= 1) {
942 int left = block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1,
943 1, size, frame->linesize[plane]);
944 int top = block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax,
945 size, 1, frame->linesize[plane]);
947 fill = ((left + top) * 2 / (2 * size) + 1) / 2;
948 } else if (ax >= 1) {
949 fill = (block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1,
950 1, size, frame->linesize[plane]) * 2 / size + 1) / 2;
951 } else if (ay >= 1) {
952 fill = (block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax,
953 size, 1, frame->linesize[plane]) * 2 / size + 1) / 2;
958 block_fill_simple(frame->data[plane] + ay * frame->linesize[plane] + ax,
959 size, frame->linesize[plane], fill);
963 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_4);
966 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_5);
969 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_6);
972 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_7);
975 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_8);
980 ret = add_coefficients(avctx, frame, ax, ay, size, plane);
985 static int get_prediction(AVCodecContext *avctx, int x, int y, int size)
987 MobiClipContext *s = avctx->priv_data;
988 GetBitContext *gb = &s->gb;
989 int index = (y & 0xC) | (x / 4 % 4);
991 uint8_t val = FFMIN(s->pre[index], index % 4 == 0 ? 9 : s->pre[index + 3]);
995 if (!get_bits1(gb)) {
996 int x = get_bits(gb, 3);
997 val = x + (x >= val ? 1 : 0);
1000 s->pre[index + 4] = val;
1002 s->pre[index + 5] = s->pre[index + 8] = s->pre[index + 9] = val;
1007 static int process_block(AVCodecContext *avctx, AVFrame *frame,
1008 int x, int y, int pmode, int has_coeffs, int plane)
1010 MobiClipContext *s = avctx->priv_data;
1011 GetBitContext *gb = &s->gb;
1016 pmode = get_prediction(avctx, x, y, 8);
1017 return predict_intra(avctx, frame, x, y, pmode, 0, 8, plane);
1020 tmp = get_ue_golomb(gb);
1021 if (tmp < 0 || tmp > FF_ARRAY_ELEMS(block4x4_coefficients_tab))
1022 return AVERROR_INVALIDDATA;
1026 pmode = get_prediction(avctx, x, y, 8);
1027 ret = predict_intra(avctx, frame, x, y, pmode, 1, 8, plane);
1029 int flags = block4x4_coefficients_tab[tmp - 1];
1031 for (int by = y; by < y + 8; by += 4) {
1032 for (int bx = x; bx < x + 8; bx += 4) {
1033 int new_pmode = pmode;
1036 new_pmode = get_prediction(avctx, bx, by, 4);
1037 ret = predict_intra(avctx, frame, bx, by, new_pmode, flags & 1, 4, plane);
1048 static int decode_macroblock(AVCodecContext *avctx, AVFrame *frame,
1049 int x, int y, int predict)
1051 MobiClipContext *s = avctx->priv_data;
1052 GetBitContext *gb = &s->gb;
1053 int flags, pmode_uv, idx = get_ue_golomb(gb);
1056 if (idx < 0 || idx >= FF_ARRAY_ELEMS(block8x8_coefficients_tab))
1057 return AVERROR_INVALIDDATA;
1059 flags = block8x8_coefficients_tab[idx];
1062 ret = process_block(avctx, frame, x, y, -1, flags & 1, 0);
1066 ret = process_block(avctx, frame, x + 8, y, -1, flags & 1, 0);
1070 ret = process_block(avctx, frame, x, y + 8, -1, flags & 1, 0);
1074 ret = process_block(avctx, frame, x + 8, y + 8, -1, flags & 1, 0);
1079 int pmode = get_bits(gb, 3);
1082 ret = predict_intra(avctx, frame, x, y, pmode, 0, 16, 0);
1088 ret = process_block(avctx, frame, x, y, pmode, flags & 1, 0);
1092 ret = process_block(avctx, frame, x + 8, y, pmode, flags & 1, 0);
1096 ret = process_block(avctx, frame, x, y + 8, pmode, flags & 1, 0);
1100 ret = process_block(avctx, frame, x + 8, y + 8, pmode, flags & 1, 0);
1106 pmode_uv = get_bits(gb, 3);
1107 if (pmode_uv == 2) {
1108 ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 1 + !s->moflex);
1111 ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 2 - !s->moflex);
1117 ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 1 + !s->moflex);
1121 ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 2 - !s->moflex);
1128 static int get_index(int x)
1130 return x == 16 ? 0 : x == 8 ? 1 : x == 4 ? 2 : x == 2 ? 3 : 0;
1133 static int predict_motion(AVCodecContext *avctx,
1134 int width, int height, int index,
1135 int offsetm, int offsetx, int offsety)
1137 MobiClipContext *s = avctx->priv_data;
1138 MotionXY *motion = s->motion;
1139 GetBitContext *gb = &s->gb;
1140 int fheight = avctx->height;
1141 int fwidth = avctx->width;
1144 int sidx = -FFMAX(1, index) + s->current_pic;
1145 MotionXY mv = s->motion[0];
1151 mv.x = mv.x + get_se_golomb(gb);
1152 mv.y = mv.y + get_se_golomb(gb);
1155 motion[offsetm].x = mv.x;
1156 motion[offsetm].y = mv.y;
1158 for (int i = 0; i < 3; i++) {
1159 int method, src_linesize, dst_linesize;
1163 offsetx = offsetx >> 1;
1164 offsety = offsety >> 1;
1168 height = height >> 1;
1169 fwidth = fwidth >> 1;
1170 fheight = fheight >> 1;
1173 av_assert0(s->pic[sidx]);
1174 av_assert0(s->pic[s->current_pic]);
1175 av_assert0(s->pic[s->current_pic]->data[i]);
1176 if (!s->pic[sidx]->data[i])
1177 return AVERROR_INVALIDDATA;
1179 method = (mv.x & 1) | ((mv.y & 1) << 1);
1180 src_linesize = s->pic[sidx]->linesize[i];
1181 dst_linesize = s->pic[s->current_pic]->linesize[i];
1182 dst = s->pic[s->current_pic]->data[i] + offsetx + offsety * dst_linesize;
1184 if (offsetx + (mv.x >> 1) < 0 ||
1185 offsety + (mv.y >> 1) < 0 ||
1186 offsetx + width + (mv.x + 1 >> 1) > fwidth ||
1187 offsety + height + (mv.y + 1 >> 1) > fheight)
1188 return AVERROR_INVALIDDATA;
1192 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1193 (offsety + (mv.y >> 1)) * src_linesize;
1194 for (int y = 0; y < height; y++) {
1195 for (int x = 0; x < width; x++)
1197 dst += dst_linesize;
1198 src += src_linesize;
1202 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1203 (offsety + (mv.y >> 1)) * src_linesize;
1204 for (int y = 0; y < height; y++) {
1205 for (int x = 0; x < width; x++) {
1206 dst[x] = (uint8_t)((src[x] >> 1) + (src[x + 1] >> 1));
1209 dst += dst_linesize;
1210 src += src_linesize;
1214 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1215 (offsety + (mv.y >> 1)) * src_linesize;
1216 for (int y = 0; y < height; y++) {
1217 for (int x = 0; x < width; x++) {
1218 dst[x] = (uint8_t)((src[x] >> 1) + (src[x + src_linesize] >> 1));
1221 dst += dst_linesize;
1222 src += src_linesize;
1226 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1227 (offsety + (mv.y >> 1)) * src_linesize;
1228 for (int y = 0; y < height; y++) {
1229 for (int x = 0; x < width; x++) {
1230 dst[x] = (uint8_t)((((src[x] >> 1) + (src[x + 1] >> 1)) >> 1) +
1231 (((src[x + src_linesize] >> 1) + (src[x + 1 + src_linesize] >> 1)) >> 1));
1234 dst += dst_linesize;
1235 src += src_linesize;
1242 int adjx = index == 8 ? 0 : width / 2;
1243 int adjy = index == 8 ? height / 2 : 0;
1245 width = width - adjx;
1246 height = height - adjy;
1247 tidx = get_index(height) * 4 + get_index(width);
1249 for (int i = 0; i < 2; i++) {
1252 idx2 = get_vlc2(gb, s->mv_vlc[s->moflex][tidx].table,
1253 MOBI_MV_VLC_BITS, 1);
1255 ret = predict_motion(avctx, width, height, idx2,
1256 offsetm, offsetx + i * adjx, offsety + i * adjy);
1265 static int mobiclip_decode(AVCodecContext *avctx, void *data,
1266 int *got_frame, AVPacket *pkt)
1268 MobiClipContext *s = avctx->priv_data;
1269 GetBitContext *gb = &s->gb;
1270 AVFrame *frame = s->pic[s->current_pic];
1273 av_fast_padded_malloc(&s->bitstream, &s->bitstream_size,
1276 if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0)
1279 s->bdsp.bswap16_buf((uint16_t *)s->bitstream,
1280 (uint16_t *)pkt->data,
1281 (pkt->size + 1) >> 1);
1283 ret = init_get_bits8(gb, s->bitstream, FFALIGN(pkt->size, 2));
1287 if (get_bits1(gb)) {
1288 frame->pict_type = AV_PICTURE_TYPE_I;
1289 frame->key_frame = 1;
1290 s->moflex = get_bits1(gb);
1291 s->dct_tab_idx = get_bits1(gb);
1293 ret = setup_qtables(avctx, get_bits(gb, 6));
1297 for (int y = 0; y < avctx->height; y += 16) {
1298 for (int x = 0; x < avctx->width; x += 16) {
1299 ret = decode_macroblock(avctx, frame, x, y, get_bits1(gb));
1305 MotionXY *motion = s->motion;
1307 memset(motion, 0, s->motion_size);
1309 frame->pict_type = AV_PICTURE_TYPE_P;
1310 frame->key_frame = 0;
1313 ret = setup_qtables(avctx, s->quantizer + get_se_golomb(gb));
1317 for (int y = 0; y < avctx->height; y += 16) {
1318 for (int x = 0; x < avctx->width; x += 16) {
1321 motion[0].x = mid_pred(motion[x / 16 + 1].x, motion[x / 16 + 2].x, motion[x / 16 + 3].x);
1322 motion[0].y = mid_pred(motion[x / 16 + 1].y, motion[x / 16 + 2].y, motion[x / 16 + 3].y);
1323 motion[x / 16 + 2].x = 0;
1324 motion[x / 16 + 2].y = 0;
1326 idx = get_vlc2(gb, s->mv_vlc[s->moflex][0].table,
1327 MOBI_MV_VLC_BITS, 1);
1329 if (idx == 6 || idx == 7) {
1330 ret = decode_macroblock(avctx, frame, x, y, idx == 7);
1335 ret = predict_motion(avctx, 16, 16, idx, x / 16 + 2, x, y);
1338 idx2 = get_ue_golomb(gb);
1339 if (idx2 >= FF_ARRAY_ELEMS(pframe_block8x8_coefficients_tab))
1340 return AVERROR_INVALIDDATA;
1341 flags = pframe_block8x8_coefficients_tab[idx2];
1343 for (int sy = y; sy < y + 16; sy += 8) {
1344 for (int sx = x; sx < x + 16; sx += 8) {
1346 add_pframe_coefficients(avctx, frame, sx, sy, 8, 0);
1352 add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 1 + !s->moflex);
1355 add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 2 - !s->moflex);
1362 avctx->colorspace = AVCOL_SPC_YCGCO;
1364 s->current_pic = (s->current_pic + 1) % 6;
1365 ret = av_frame_ref(data, frame);
1373 static void mobiclip_flush(AVCodecContext *avctx)
1375 MobiClipContext *s = avctx->priv_data;
1377 for (int i = 0; i < 6; i++)
1378 av_frame_unref(s->pic[i]);
1381 static av_cold int mobiclip_close(AVCodecContext *avctx)
1383 MobiClipContext *s = avctx->priv_data;
1385 ff_free_vlc(&s->vlc[0]);
1386 ff_free_vlc(&s->vlc[1]);
1388 for (int i = 0; i < 16; i++) {
1389 ff_free_vlc(&s->mv_vlc[0][i]);
1390 ff_free_vlc(&s->mv_vlc[1][i]);
1393 av_freep(&s->bitstream);
1394 s->bitstream_size = 0;
1395 av_freep(&s->motion);
1398 for (int i = 0; i < 6; i++) {
1399 av_frame_free(&s->pic[i]);
1405 AVCodec ff_mobiclip_decoder = {
1407 .long_name = NULL_IF_CONFIG_SMALL("MobiClip Video"),
1408 .type = AVMEDIA_TYPE_VIDEO,
1409 .id = AV_CODEC_ID_MOBICLIP,
1410 .priv_data_size = sizeof(MobiClipContext),
1411 .init = mobiclip_init,
1412 .decode = mobiclip_decode,
1413 .flush = mobiclip_flush,
1414 .close = mobiclip_close,
1415 .capabilities = AV_CODEC_CAP_DR1,
1416 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,