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 void setup_qtables(AVCodecContext *avctx, int quantizer)
387 MobiClipContext *s = avctx->priv_data;
390 s->quantizer = quantizer;
395 for (int i = 0; i < 16; i++)
396 s->qtab[0][i] = quant4x4_tab[qx][i] << qy;
398 for (int i = 0; i < 64; i++)
399 s->qtab[1][i] = quant8x8_tab[qx][i] << (qy - 2);
401 for (int i = 0; i < 20; i++)
405 static void inverse4(int *rs)
407 int a = rs[0] + rs[2];
408 int b = rs[0] - rs[2];
409 int c = rs[1] + (rs[3] >> 1);
410 int d = (rs[1] >> 1) - rs[3];
418 static void idct(int *arr, int size)
420 int e, f, g, h, x3, x2, x1, x0;
435 e = arr[7] + arr[1] - arr[3] - (arr[3] >> 1);
436 f = arr[7] - arr[1] + arr[5] + (arr[5] >> 1);
437 g = arr[5] - arr[3] - arr[7] - (arr[7] >> 1);
438 h = arr[5] + arr[3] + arr[1] + (arr[1] >> 1);
444 arr[0] = tmp[0] + x0;
445 arr[1] = tmp[1] + x1;
446 arr[2] = tmp[2] + x2;
447 arr[3] = tmp[3] + x3;
448 arr[4] = tmp[3] - x3;
449 arr[5] = tmp[2] - x2;
450 arr[6] = tmp[1] - x1;
451 arr[7] = tmp[0] - x0;
454 static int read_run_encoding(AVCodecContext *avctx,
455 int *last, int *run, int *level)
457 MobiClipContext *s = avctx->priv_data;
458 GetBitContext *gb = &s->gb;
459 int n = get_vlc2(gb, s->vlc[s->dct_tab_idx].table,
460 s->vlc[s->dct_tab_idx].bits, 2);
463 return AVERROR_INVALIDDATA;
465 *last = (n >> 11) == 1;
466 *run = (n >> 5) & 0x3F;
472 static int add_coefficients(AVCodecContext *avctx, AVFrame *frame,
473 int bx, int by, int size, int plane)
475 MobiClipContext *s = avctx->priv_data;
476 GetBitContext *gb = &s->gb;
478 const uint8_t *ztab = size == 8 ? ff_zigzag_direct : zigzag4x4_tab;
479 const int *qtab = s->qtab[size == 8];
480 uint8_t *dst = frame->data[plane] + by * frame->linesize[plane] + bx;
483 for (int pos = 0; get_bits_left(gb) > 0; pos++) {
484 int qval, last, run, level;
486 ret = read_run_encoding(avctx, &last, &run, &level);
493 } else if (!get_bits1(gb)) {
494 ret = read_run_encoding(avctx, &last, &run, &level);
497 level += run_residue[s->dct_tab_idx][(last ? 64 : 0) + run];
500 } else if (!get_bits1(gb)) {
501 ret = read_run_encoding(avctx, &last, &run, &level);
504 run += run_residue[s->dct_tab_idx][128 + (last ? 64 : 0) + level];
508 last = get_bits1(gb);
509 run = get_bits(gb, 6);
510 level = get_sbits(gb, 12);
514 if (pos >= size * size)
515 return AVERROR_INVALIDDATA;
517 mat[ztab[pos]] = qval * level;
524 for (int y = 0; y < size; y++)
525 idct(&mat[y * size], size);
527 for (int y = 0; y < size; y++) {
528 for (int x = y + 1; x < size; x++) {
529 int a = mat[x * size + y];
530 int b = mat[y * size + x];
532 mat[y * size + x] = a;
533 mat[x * size + y] = b;
536 idct(&mat[y * size], size);
537 for (int x = 0; x < size; x++)
538 dst[x] = av_clip_uint8(dst[x] + (mat[y * size + x] >> 6));
539 dst += frame->linesize[plane];
545 static int add_pframe_coefficients(AVCodecContext *avctx, AVFrame *frame,
546 int bx, int by, int size, int plane)
548 MobiClipContext *s = avctx->priv_data;
549 GetBitContext *gb = &s->gb;
550 int ret, idx = get_ue_golomb(gb);
553 ret = add_coefficients(avctx, frame, bx, by, size, plane);
554 } else if (idx < FF_ARRAY_ELEMS(pframe_block4x4_coefficients_tab)) {
555 int flags = pframe_block4x4_coefficients_tab[idx];
557 for (int y = by; y < by + 8; y += 4) {
558 for (int x = bx; x < bx + 8; x += 4) {
560 ret = add_coefficients(avctx, frame, x, y, 4, plane);
568 ret = AVERROR_INVALIDDATA;
574 static int adjust(int x, int size)
576 return size == 16 ? (x + 1) >> 1 : x;
579 static uint8_t pget(BlockXY b)
584 if (b.x == -1 && b.y >= b.size) {
585 ret.x = -1, ret.y = b.size - 1;
586 } else if (b.x >= -1 && b.y >= -1) {
587 ret.x = b.x, ret.y = b.y;
588 } else if (b.x == -1 && b.y == -2) {
589 ret.x = 0, ret.y = -1;
590 } else if (b.x == -2 && b.y == -1) {
591 ret.x = -1, ret.y = 0;
594 y = av_clip(ret.ay + ret.y, 0, ret.h - 1);
595 x = av_clip(ret.ax + ret.x, 0, ret.w - 1);
597 return ret.block[y * ret.linesize + x];
600 static uint8_t half(int a, int b)
602 return ((a + b) + 1) / 2;
605 static uint8_t half3(int a, int b, int c)
607 return ((a + b + b + c) * 2 / 4 + 1) / 2;;
610 static uint8_t pick_above(BlockXY bxy)
617 static uint8_t pick_left(BlockXY bxy)
624 static uint8_t half_horz(BlockXY bxy)
626 BlockXY a = bxy, b = bxy, c = bxy;
631 return half3(pget(a), pget(b), pget(c));
634 static uint8_t half_vert(BlockXY bxy)
636 BlockXY a = bxy, b = bxy, c = bxy;
641 return half3(pget(a), pget(b), pget(c));
644 static uint8_t pick_4(BlockXY bxy)
648 if ((bxy.x % 2) == 0) {
654 ba.y = bxy.y + bxy.x / 2;
659 bb.y = bxy.y + bxy.x / 2 + 1;
668 ba.y = bxy.y + bxy.x / 2 + 1;
675 static uint8_t pick_5(BlockXY bxy)
688 val = half(pget(a), pget(b));
689 } else if (bxy.y == 0) {
696 } else if (bxy.x == 1) {
715 static uint8_t pick_6(BlockXY bxy)
728 val = half(pget(a), pget(b));
729 } else if (bxy.x == 0) {
736 } else if (bxy.y == 1) {
755 static uint8_t pick_7(BlockXY bxy)
784 return half3(acc1, clr, acc2);
787 static uint8_t pick_8(BlockXY bxy)
805 } else if (bxy.y == 1) {
810 } else if (bxy.x < bxy.size - 1) {
815 } else if (bxy.y % 2 == 0) {
818 ba.x = bxy.y / 2 + bxy.size - 1;
822 bb.x = bxy.y / 2 + bxy.size;
829 ba.x = bxy.y / 2 + bxy.size;
838 static void block_fill_simple(uint8_t *block, int size, int linesize, int fill)
840 for (int y = 0; y < size; y++) {
841 memset(block, fill, size);
846 static void block_fill(uint8_t *block, int size, int linesize,
847 int w, int h, int ax, int ay,
848 uint8_t (*pick)(BlockXY bxy))
854 bxy.linesize = linesize;
860 for (int y = 0; y < size; y++) {
862 for (int x = 0; x < size; x++) {
869 block[ax + x + (ay + y) * linesize] = val;
874 static int block_sum(const uint8_t *block, int w, int h, int linesize)
878 for (int y = 0; y < h; y++) {
879 for (int x = 0; x < w; x++) {
888 static int predict_intra(AVCodecContext *avctx, AVFrame *frame, int ax, int ay,
889 int pmode, int add_coeffs, int size, int plane)
891 MobiClipContext *s = avctx->priv_data;
892 GetBitContext *gb = &s->gb;
893 int w = avctx->width >> !!plane, h = avctx->height >> !!plane;
898 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_above);
901 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_left);
907 uint8_t *top = frame->data[plane] + FFMAX(ay - 1, 0) * frame->linesize[plane] + ax;
908 uint8_t *left = frame->data[plane] + ay * frame->linesize[plane] + FFMAX(ax - 1, 0);
909 int bottommost = frame->data[plane][(ay + size - 1) * frame->linesize[plane] + FFMAX(ax - 1, 0)];
910 int rightmost = frame->data[plane][FFMAX(ay - 1, 0) * frame->linesize[plane] + ax + size - 1];
911 int avg = (bottommost + rightmost + 1) / 2 + 2 * get_se_golomb(gb);
912 int r6 = adjust(avg - bottommost, size);
913 int r9 = adjust(avg - rightmost, size);
914 int shift = adjust(size, size) == 8 ? 3 : 2;
917 for (int x = 0; x < size; x++) {
919 arr1[x] = adjust(((bottommost - val) * (1 << shift)) + r6 * (x + 1), size);
922 for (int y = 0; y < size; y++) {
923 int val = left[y * frame->linesize[plane]];
924 arr2[y] = adjust(((rightmost - val) * (1 << shift)) + r9 * (y + 1), size);
927 block = frame->data[plane] + ay * frame->linesize[plane] + ax;
928 for (int y = 0; y < size; y++) {
929 for (int x = 0; x < size; x++) {
930 block[x] = (((top[x] + left[0] + ((arr1[x] * (y + 1) +
931 arr2[y] * (x + 1)) >> 2 * shift)) + 1) / 2) & 0xFF;
933 block += frame->linesize[plane];
934 left += frame->linesize[plane];
942 if (ax == 0 && ay == 0) {
944 } else if (ax >= 1 && ay >= 1) {
945 int left = block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1,
946 1, size, frame->linesize[plane]);
947 int top = block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax,
948 size, 1, frame->linesize[plane]);
950 fill = ((left + top) * 2 / (2 * size) + 1) / 2;
951 } else if (ax >= 1) {
952 fill = (block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1,
953 1, size, frame->linesize[plane]) * 2 / size + 1) / 2;
954 } else if (ay >= 1) {
955 fill = (block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax,
956 size, 1, frame->linesize[plane]) * 2 / size + 1) / 2;
961 block_fill_simple(frame->data[plane] + ay * frame->linesize[plane] + ax,
962 size, frame->linesize[plane], fill);
966 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_4);
969 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_5);
972 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_6);
975 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_7);
978 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_8);
983 ret = add_coefficients(avctx, frame, ax, ay, size, plane);
988 static int get_prediction(AVCodecContext *avctx, int x, int y, int size)
990 MobiClipContext *s = avctx->priv_data;
991 GetBitContext *gb = &s->gb;
992 int index = (y & 0xC) | (x / 4 % 4);
994 uint8_t val = FFMIN(s->pre[index], index % 4 == 0 ? 9 : s->pre[index + 3]);
998 if (!get_bits1(gb)) {
999 int x = get_bits(gb, 3);
1000 val = x + (x >= val ? 1 : 0);
1003 s->pre[index + 4] = val;
1005 s->pre[index + 5] = s->pre[index + 8] = s->pre[index + 9] = val;
1010 static int process_block(AVCodecContext *avctx, AVFrame *frame,
1011 int x, int y, int pmode, int has_coeffs, int plane)
1013 MobiClipContext *s = avctx->priv_data;
1014 GetBitContext *gb = &s->gb;
1019 pmode = get_prediction(avctx, x, y, 8);
1020 return predict_intra(avctx, frame, x, y, pmode, 0, 8, plane);
1023 tmp = get_ue_golomb(gb);
1024 if (tmp < 0 || tmp > FF_ARRAY_ELEMS(block4x4_coefficients_tab))
1025 return AVERROR_INVALIDDATA;
1029 pmode = get_prediction(avctx, x, y, 8);
1030 ret = predict_intra(avctx, frame, x, y, pmode, 1, 8, plane);
1032 int flags = block4x4_coefficients_tab[tmp - 1];
1034 for (int by = y; by < y + 8; by += 4) {
1035 for (int bx = x; bx < x + 8; bx += 4) {
1036 int new_pmode = pmode;
1039 new_pmode = get_prediction(avctx, bx, by, 4);
1040 ret = predict_intra(avctx, frame, bx, by, new_pmode, flags & 1, 4, plane);
1051 static int decode_macroblock(AVCodecContext *avctx, AVFrame *frame,
1052 int x, int y, int predict)
1054 MobiClipContext *s = avctx->priv_data;
1055 GetBitContext *gb = &s->gb;
1056 int flags, pmode_uv, idx = get_ue_golomb(gb);
1059 if (idx < 0 || idx >= FF_ARRAY_ELEMS(block8x8_coefficients_tab))
1060 return AVERROR_INVALIDDATA;
1062 flags = block8x8_coefficients_tab[idx];
1065 ret = process_block(avctx, frame, x, y, -1, flags & 1, 0);
1069 ret = process_block(avctx, frame, x + 8, y, -1, flags & 1, 0);
1073 ret = process_block(avctx, frame, x, y + 8, -1, flags & 1, 0);
1077 ret = process_block(avctx, frame, x + 8, y + 8, -1, flags & 1, 0);
1082 int pmode = get_bits(gb, 3);
1085 ret = predict_intra(avctx, frame, x, y, pmode, 0, 16, 0);
1091 ret = process_block(avctx, frame, x, y, pmode, flags & 1, 0);
1095 ret = process_block(avctx, frame, x + 8, y, pmode, flags & 1, 0);
1099 ret = process_block(avctx, frame, x, y + 8, pmode, flags & 1, 0);
1103 ret = process_block(avctx, frame, x + 8, y + 8, pmode, flags & 1, 0);
1109 pmode_uv = get_bits(gb, 3);
1110 if (pmode_uv == 2) {
1111 ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 1 + !s->moflex);
1114 ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 2 - !s->moflex);
1120 ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 1 + !s->moflex);
1124 ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 2 - !s->moflex);
1131 static int get_index(int x)
1133 return x == 16 ? 0 : x == 8 ? 1 : x == 4 ? 2 : x == 2 ? 3 : 0;
1136 static int predict_motion(AVCodecContext *avctx,
1137 int width, int height, int index,
1138 int offsetm, int offsetx, int offsety)
1140 MobiClipContext *s = avctx->priv_data;
1141 MotionXY *motion = s->motion;
1142 GetBitContext *gb = &s->gb;
1143 int fheight = avctx->height;
1144 int fwidth = avctx->width;
1147 int sidx = -FFMAX(1, index) + s->current_pic;
1148 MotionXY mv = s->motion[0];
1154 mv.x = mv.x + get_se_golomb(gb);
1155 mv.y = mv.y + get_se_golomb(gb);
1158 motion[offsetm].x = mv.x;
1159 motion[offsetm].y = mv.y;
1161 for (int i = 0; i < 3; i++) {
1162 int method, src_linesize, dst_linesize;
1166 offsetx = offsetx >> 1;
1167 offsety = offsety >> 1;
1171 height = height >> 1;
1172 fwidth = fwidth >> 1;
1173 fheight = fheight >> 1;
1176 av_assert0(s->pic[sidx]);
1177 av_assert0(s->pic[s->current_pic]);
1178 av_assert0(s->pic[s->current_pic]->data[i]);
1179 if (!s->pic[sidx]->data[i])
1180 return AVERROR_INVALIDDATA;
1182 method = (mv.x & 1) | ((mv.y & 1) << 1);
1183 src_linesize = s->pic[sidx]->linesize[i];
1184 dst_linesize = s->pic[s->current_pic]->linesize[i];
1185 dst = s->pic[s->current_pic]->data[i] + offsetx + offsety * dst_linesize;
1189 if (offsety + (mv.y >> 1) < 0 ||
1190 offsety + (mv.y >> 1) >= fheight ||
1191 offsetx + (mv.x >> 1) < 0 ||
1192 offsetx + (mv.x >> 1) >= fwidth)
1193 return AVERROR_INVALIDDATA;
1195 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1196 (offsety + (mv.y >> 1)) * src_linesize;
1197 for (int y = 0; y < height; y++) {
1198 for (int x = 0; x < width; x++)
1200 dst += dst_linesize;
1201 src += src_linesize;
1205 if (offsety + (mv.y >> 1) < 0 ||
1206 offsety + (mv.y >> 1) >= fheight ||
1207 offsetx + (mv.x >> 1) < 0 ||
1208 offsetx + (mv.x >> 1) >= fwidth)
1209 return AVERROR_INVALIDDATA;
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 if (offsety + (mv.y >> 1) < 0 ||
1224 offsety + (mv.y >> 1) >= fheight - 1 ||
1225 offsetx + (mv.x >> 1) < 0 ||
1226 offsetx + (mv.x >> 1) >= fwidth)
1227 return AVERROR_INVALIDDATA;
1229 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1230 (offsety + (mv.y >> 1)) * src_linesize;
1231 for (int y = 0; y < height; y++) {
1232 for (int x = 0; x < width; x++) {
1233 dst[x] = (uint8_t)((src[x] >> 1) + (src[x + src_linesize] >> 1));
1236 dst += dst_linesize;
1237 src += src_linesize;
1241 if (offsety + (mv.y >> 1) < 0 ||
1242 offsety + (mv.y >> 1) >= fheight - 1 ||
1243 offsetx + (mv.x >> 1) < 0 ||
1244 offsetx + (mv.x >> 1) >= fwidth)
1245 return AVERROR_INVALIDDATA;
1247 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1248 (offsety + (mv.y >> 1)) * src_linesize;
1249 for (int y = 0; y < height; y++) {
1250 for (int x = 0; x < width; x++) {
1251 dst[x] = (uint8_t)((((src[x] >> 1) + (src[x + 1] >> 1)) >> 1) +
1252 (((src[x + src_linesize] >> 1) + (src[x + 1 + src_linesize] >> 1)) >> 1));
1255 dst += dst_linesize;
1256 src += src_linesize;
1263 int adjx = index == 8 ? 0 : width / 2;
1264 int adjy = index == 8 ? height / 2 : 0;
1266 width = width - adjx;
1267 height = height - adjy;
1268 tidx = get_index(height) * 4 + get_index(width);
1270 for (int i = 0; i < 2; i++) {
1273 idx2 = get_vlc2(gb, s->mv_vlc[s->moflex][tidx].table,
1274 s->mv_vlc[s->moflex][tidx].bits, 1);
1276 return AVERROR_INVALIDDATA;
1278 ret = predict_motion(avctx, width, height, idx2,
1279 offsetm, offsetx + i * adjx, offsety + i * adjy);
1288 static int mobiclip_decode(AVCodecContext *avctx, void *data,
1289 int *got_frame, AVPacket *pkt)
1291 MobiClipContext *s = avctx->priv_data;
1292 GetBitContext *gb = &s->gb;
1293 AVFrame *frame = s->pic[s->current_pic];
1296 av_fast_padded_malloc(&s->bitstream, &s->bitstream_size,
1299 if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0)
1302 s->bdsp.bswap16_buf((uint16_t *)s->bitstream,
1303 (uint16_t *)pkt->data,
1304 (pkt->size + 1) >> 1);
1306 ret = init_get_bits8(gb, s->bitstream, s->bitstream_size);
1310 if (get_bits1(gb)) {
1311 frame->pict_type = AV_PICTURE_TYPE_I;
1312 frame->key_frame = 1;
1313 s->moflex = get_bits1(gb);
1314 s->dct_tab_idx = get_bits1(gb);
1316 setup_qtables(avctx, get_bits(gb, 6));
1317 for (int y = 0; y < avctx->height; y += 16) {
1318 for (int x = 0; x < avctx->width; x += 16) {
1319 ret = decode_macroblock(avctx, frame, x, y, get_bits1(gb));
1325 MotionXY *motion = s->motion;
1326 int quantizer = s->quantizer + get_se_golomb(gb);
1328 if (quantizer < 12 || quantizer > 161)
1329 return AVERROR_INVALIDDATA;
1331 memset(motion, 0, s->motion_size);
1333 frame->pict_type = AV_PICTURE_TYPE_P;
1334 frame->key_frame = 0;
1337 setup_qtables(avctx, quantizer);
1338 for (int y = 0; y < avctx->height; y += 16) {
1339 for (int x = 0; x < avctx->width; x += 16) {
1342 motion[0].x = mid_pred(motion[x / 16 + 1].x, motion[x / 16 + 2].x, motion[x / 16 + 3].x);
1343 motion[0].y = mid_pred(motion[x / 16 + 1].y, motion[x / 16 + 2].y, motion[x / 16 + 3].y);
1344 motion[x / 16 + 2].x = 0;
1345 motion[x / 16 + 2].y = 0;
1347 idx = get_vlc2(gb, s->mv_vlc[s->moflex][0].table,
1348 s->mv_vlc[s->moflex][0].bits, 1);
1350 return AVERROR_INVALIDDATA;
1352 if (idx == 6 || idx == 7) {
1353 ret = decode_macroblock(avctx, frame, x, y, idx == 7);
1358 ret = predict_motion(avctx, 16, 16, idx, x / 16 + 2, x, y);
1361 idx2 = get_ue_golomb(gb);
1362 if (idx2 >= FF_ARRAY_ELEMS(pframe_block8x8_coefficients_tab))
1363 return AVERROR_INVALIDDATA;
1364 flags = pframe_block8x8_coefficients_tab[idx2];
1366 for (int sy = y; sy < y + 16; sy += 8) {
1367 for (int sx = x; sx < x + 16; sx += 8) {
1369 add_pframe_coefficients(avctx, frame, sx, sy, 8, 0);
1375 add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 1 + !s->moflex);
1378 add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 2 - !s->moflex);
1385 avctx->colorspace = AVCOL_SPC_YCGCO;
1387 s->current_pic = (s->current_pic + 1) % 6;
1388 ret = av_frame_ref(data, frame);
1396 static void mobiclip_flush(AVCodecContext *avctx)
1398 MobiClipContext *s = avctx->priv_data;
1400 for (int i = 0; i < 6; i++)
1401 av_frame_unref(s->pic[i]);
1404 static av_cold int mobiclip_close(AVCodecContext *avctx)
1406 MobiClipContext *s = avctx->priv_data;
1408 ff_free_vlc(&s->vlc[0]);
1409 ff_free_vlc(&s->vlc[1]);
1411 for (int i = 0; i < 16; i++) {
1412 ff_free_vlc(&s->mv_vlc[0][i]);
1413 ff_free_vlc(&s->mv_vlc[1][i]);
1416 av_freep(&s->bitstream);
1417 s->bitstream_size = 0;
1418 av_freep(&s->motion);
1421 for (int i = 0; i < 6; i++) {
1422 av_frame_free(&s->pic[i]);
1428 AVCodec ff_mobiclip_decoder = {
1430 .long_name = NULL_IF_CONFIG_SMALL("MobiClip Video"),
1431 .type = AVMEDIA_TYPE_VIDEO,
1432 .id = AV_CODEC_ID_MOBICLIP,
1433 .priv_data_size = sizeof(MobiClipContext),
1434 .init = mobiclip_init,
1435 .decode = mobiclip_decode,
1436 .flush = mobiclip_flush,
1437 .close = mobiclip_close,
1438 .capabilities = AV_CODEC_CAP_DR1,
1439 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,