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(int *rs)
412 int a = rs[0] + rs[2];
413 int b = rs[0] - rs[2];
414 int c = rs[1] + (rs[3] >> 1);
415 int d = (rs[1] >> 1) - rs[3];
423 static void idct(int *arr, int size)
425 int e, f, g, h, x3, x2, x1, x0;
440 e = arr[7] + arr[1] - arr[3] - (arr[3] >> 1);
441 f = arr[7] - arr[1] + arr[5] + (arr[5] >> 1);
442 g = arr[5] - arr[3] - arr[7] - (arr[7] >> 1);
443 h = arr[5] + arr[3] + arr[1] + (arr[1] >> 1);
449 arr[0] = tmp[0] + x0;
450 arr[1] = tmp[1] + x1;
451 arr[2] = tmp[2] + x2;
452 arr[3] = tmp[3] + x3;
453 arr[4] = tmp[3] - x3;
454 arr[5] = tmp[2] - x2;
455 arr[6] = tmp[1] - x1;
456 arr[7] = tmp[0] - x0;
459 static int read_run_encoding(AVCodecContext *avctx,
460 int *last, int *run, int *level)
462 MobiClipContext *s = avctx->priv_data;
463 GetBitContext *gb = &s->gb;
464 int n = get_vlc2(gb, s->vlc[s->dct_tab_idx].table,
465 s->vlc[s->dct_tab_idx].bits, 2);
468 return AVERROR_INVALIDDATA;
470 *last = (n >> 11) == 1;
471 *run = (n >> 5) & 0x3F;
477 static int add_coefficients(AVCodecContext *avctx, AVFrame *frame,
478 int bx, int by, int size, int plane)
480 MobiClipContext *s = avctx->priv_data;
481 GetBitContext *gb = &s->gb;
483 const uint8_t *ztab = size == 8 ? ff_zigzag_direct : zigzag4x4_tab;
484 const int *qtab = s->qtab[size == 8];
485 uint8_t *dst = frame->data[plane] + by * frame->linesize[plane] + bx;
488 for (int pos = 0; get_bits_left(gb) > 0; pos++) {
489 int qval, last, run, level;
491 ret = read_run_encoding(avctx, &last, &run, &level);
498 } else if (!get_bits1(gb)) {
499 ret = read_run_encoding(avctx, &last, &run, &level);
502 level += run_residue[s->dct_tab_idx][(last ? 64 : 0) + run];
505 } else if (!get_bits1(gb)) {
506 ret = read_run_encoding(avctx, &last, &run, &level);
509 run += run_residue[s->dct_tab_idx][128 + (last ? 64 : 0) + level];
513 last = get_bits1(gb);
514 run = get_bits(gb, 6);
515 level = get_sbits(gb, 12);
519 if (pos >= size * size)
520 return AVERROR_INVALIDDATA;
522 mat[ztab[pos]] = qval * level;
529 for (int y = 0; y < size; y++)
530 idct(&mat[y * size], size);
532 for (int y = 0; y < size; y++) {
533 for (int x = y + 1; x < size; x++) {
534 int a = mat[x * size + y];
535 int b = mat[y * size + x];
537 mat[y * size + x] = a;
538 mat[x * size + y] = b;
541 idct(&mat[y * size], size);
542 for (int x = 0; x < size; x++)
543 dst[x] = av_clip_uint8(dst[x] + (mat[y * size + x] >> 6));
544 dst += frame->linesize[plane];
550 static int add_pframe_coefficients(AVCodecContext *avctx, AVFrame *frame,
551 int bx, int by, int size, int plane)
553 MobiClipContext *s = avctx->priv_data;
554 GetBitContext *gb = &s->gb;
555 int ret, idx = get_ue_golomb(gb);
558 ret = add_coefficients(avctx, frame, bx, by, size, plane);
559 } else if (idx < FF_ARRAY_ELEMS(pframe_block4x4_coefficients_tab)) {
560 int flags = pframe_block4x4_coefficients_tab[idx];
562 for (int y = by; y < by + 8; y += 4) {
563 for (int x = bx; x < bx + 8; x += 4) {
565 ret = add_coefficients(avctx, frame, x, y, 4, plane);
573 ret = AVERROR_INVALIDDATA;
579 static int adjust(int x, int size)
581 return size == 16 ? (x + 1) >> 1 : x;
584 static uint8_t pget(BlockXY b)
589 if (b.x == -1 && b.y >= b.size) {
590 ret.x = -1, ret.y = b.size - 1;
591 } else if (b.x >= -1 && b.y >= -1) {
592 ret.x = b.x, ret.y = b.y;
593 } else if (b.x == -1 && b.y == -2) {
594 ret.x = 0, ret.y = -1;
595 } else if (b.x == -2 && b.y == -1) {
596 ret.x = -1, ret.y = 0;
599 y = av_clip(ret.ay + ret.y, 0, ret.h - 1);
600 x = av_clip(ret.ax + ret.x, 0, ret.w - 1);
602 return ret.block[y * ret.linesize + x];
605 static uint8_t half(int a, int b)
607 return ((a + b) + 1) / 2;
610 static uint8_t half3(int a, int b, int c)
612 return ((a + b + b + c) * 2 / 4 + 1) / 2;;
615 static uint8_t pick_above(BlockXY bxy)
622 static uint8_t pick_left(BlockXY bxy)
629 static uint8_t half_horz(BlockXY bxy)
631 BlockXY a = bxy, b = bxy, c = bxy;
636 return half3(pget(a), pget(b), pget(c));
639 static uint8_t half_vert(BlockXY bxy)
641 BlockXY a = bxy, b = bxy, c = bxy;
646 return half3(pget(a), pget(b), pget(c));
649 static uint8_t pick_4(BlockXY bxy)
653 if ((bxy.x % 2) == 0) {
659 ba.y = bxy.y + bxy.x / 2;
664 bb.y = bxy.y + bxy.x / 2 + 1;
673 ba.y = bxy.y + bxy.x / 2 + 1;
680 static uint8_t pick_5(BlockXY bxy)
693 val = half(pget(a), pget(b));
694 } else if (bxy.y == 0) {
701 } else if (bxy.x == 1) {
720 static uint8_t pick_6(BlockXY bxy)
733 val = half(pget(a), pget(b));
734 } else if (bxy.x == 0) {
741 } else if (bxy.y == 1) {
760 static uint8_t pick_7(BlockXY bxy)
789 return half3(acc1, clr, acc2);
792 static uint8_t pick_8(BlockXY bxy)
810 } else if (bxy.y == 1) {
815 } else if (bxy.x < bxy.size - 1) {
820 } else if (bxy.y % 2 == 0) {
823 ba.x = bxy.y / 2 + bxy.size - 1;
827 bb.x = bxy.y / 2 + bxy.size;
834 ba.x = bxy.y / 2 + bxy.size;
843 static void block_fill_simple(uint8_t *block, int size, int linesize, int fill)
845 for (int y = 0; y < size; y++) {
846 memset(block, fill, size);
851 static void block_fill(uint8_t *block, int size, int linesize,
852 int w, int h, int ax, int ay,
853 uint8_t (*pick)(BlockXY bxy))
859 bxy.linesize = linesize;
865 for (int y = 0; y < size; y++) {
867 for (int x = 0; x < size; x++) {
874 block[ax + x + (ay + y) * linesize] = val;
879 static int block_sum(const uint8_t *block, int w, int h, int linesize)
883 for (int y = 0; y < h; y++) {
884 for (int x = 0; x < w; x++) {
893 static int predict_intra(AVCodecContext *avctx, AVFrame *frame, int ax, int ay,
894 int pmode, int add_coeffs, int size, int plane)
896 MobiClipContext *s = avctx->priv_data;
897 GetBitContext *gb = &s->gb;
898 int w = avctx->width >> !!plane, h = avctx->height >> !!plane;
903 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_above);
906 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_left);
912 uint8_t *top = frame->data[plane] + FFMAX(ay - 1, 0) * frame->linesize[plane] + ax;
913 uint8_t *left = frame->data[plane] + ay * frame->linesize[plane] + FFMAX(ax - 1, 0);
914 int bottommost = frame->data[plane][(ay + size - 1) * frame->linesize[plane] + FFMAX(ax - 1, 0)];
915 int rightmost = frame->data[plane][FFMAX(ay - 1, 0) * frame->linesize[plane] + ax + size - 1];
916 int avg = (bottommost + rightmost + 1) / 2 + 2 * get_se_golomb(gb);
917 int r6 = adjust(avg - bottommost, size);
918 int r9 = adjust(avg - rightmost, size);
919 int shift = adjust(size, size) == 8 ? 3 : 2;
922 for (int x = 0; x < size; x++) {
924 arr1[x] = adjust(((bottommost - val) * (1 << shift)) + r6 * (x + 1), size);
927 for (int y = 0; y < size; y++) {
928 int val = left[y * frame->linesize[plane]];
929 arr2[y] = adjust(((rightmost - val) * (1 << shift)) + r9 * (y + 1), size);
932 block = frame->data[plane] + ay * frame->linesize[plane] + ax;
933 for (int y = 0; y < size; y++) {
934 for (int x = 0; x < size; x++) {
935 block[x] = (((top[x] + left[0] + ((arr1[x] * (y + 1) +
936 arr2[y] * (x + 1)) >> 2 * shift)) + 1) / 2) & 0xFF;
938 block += frame->linesize[plane];
939 left += frame->linesize[plane];
947 if (ax == 0 && ay == 0) {
949 } else if (ax >= 1 && ay >= 1) {
950 int left = block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1,
951 1, size, frame->linesize[plane]);
952 int top = block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax,
953 size, 1, frame->linesize[plane]);
955 fill = ((left + top) * 2 / (2 * size) + 1) / 2;
956 } else if (ax >= 1) {
957 fill = (block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1,
958 1, size, frame->linesize[plane]) * 2 / size + 1) / 2;
959 } else if (ay >= 1) {
960 fill = (block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax,
961 size, 1, frame->linesize[plane]) * 2 / size + 1) / 2;
966 block_fill_simple(frame->data[plane] + ay * frame->linesize[plane] + ax,
967 size, frame->linesize[plane], fill);
971 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_4);
974 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_5);
977 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_6);
980 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_7);
983 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_8);
988 ret = add_coefficients(avctx, frame, ax, ay, size, plane);
993 static int get_prediction(AVCodecContext *avctx, int x, int y, int size)
995 MobiClipContext *s = avctx->priv_data;
996 GetBitContext *gb = &s->gb;
997 int index = (y & 0xC) | (x / 4 % 4);
999 uint8_t val = FFMIN(s->pre[index], index % 4 == 0 ? 9 : s->pre[index + 3]);
1003 if (!get_bits1(gb)) {
1004 int x = get_bits(gb, 3);
1005 val = x + (x >= val ? 1 : 0);
1008 s->pre[index + 4] = val;
1010 s->pre[index + 5] = s->pre[index + 8] = s->pre[index + 9] = val;
1015 static int process_block(AVCodecContext *avctx, AVFrame *frame,
1016 int x, int y, int pmode, int has_coeffs, int plane)
1018 MobiClipContext *s = avctx->priv_data;
1019 GetBitContext *gb = &s->gb;
1024 pmode = get_prediction(avctx, x, y, 8);
1025 return predict_intra(avctx, frame, x, y, pmode, 0, 8, plane);
1028 tmp = get_ue_golomb(gb);
1029 if (tmp < 0 || tmp > FF_ARRAY_ELEMS(block4x4_coefficients_tab))
1030 return AVERROR_INVALIDDATA;
1034 pmode = get_prediction(avctx, x, y, 8);
1035 ret = predict_intra(avctx, frame, x, y, pmode, 1, 8, plane);
1037 int flags = block4x4_coefficients_tab[tmp - 1];
1039 for (int by = y; by < y + 8; by += 4) {
1040 for (int bx = x; bx < x + 8; bx += 4) {
1041 int new_pmode = pmode;
1044 new_pmode = get_prediction(avctx, bx, by, 4);
1045 ret = predict_intra(avctx, frame, bx, by, new_pmode, flags & 1, 4, plane);
1056 static int decode_macroblock(AVCodecContext *avctx, AVFrame *frame,
1057 int x, int y, int predict)
1059 MobiClipContext *s = avctx->priv_data;
1060 GetBitContext *gb = &s->gb;
1061 int flags, pmode_uv, idx = get_ue_golomb(gb);
1064 if (idx < 0 || idx >= FF_ARRAY_ELEMS(block8x8_coefficients_tab))
1065 return AVERROR_INVALIDDATA;
1067 flags = block8x8_coefficients_tab[idx];
1070 ret = process_block(avctx, frame, x, y, -1, flags & 1, 0);
1074 ret = process_block(avctx, frame, x + 8, y, -1, flags & 1, 0);
1078 ret = process_block(avctx, frame, x, y + 8, -1, flags & 1, 0);
1082 ret = process_block(avctx, frame, x + 8, y + 8, -1, flags & 1, 0);
1087 int pmode = get_bits(gb, 3);
1090 ret = predict_intra(avctx, frame, x, y, pmode, 0, 16, 0);
1096 ret = process_block(avctx, frame, x, y, pmode, flags & 1, 0);
1100 ret = process_block(avctx, frame, x + 8, y, pmode, flags & 1, 0);
1104 ret = process_block(avctx, frame, x, y + 8, pmode, flags & 1, 0);
1108 ret = process_block(avctx, frame, x + 8, y + 8, pmode, flags & 1, 0);
1114 pmode_uv = get_bits(gb, 3);
1115 if (pmode_uv == 2) {
1116 ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 1 + !s->moflex);
1119 ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 2 - !s->moflex);
1125 ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 1 + !s->moflex);
1129 ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 2 - !s->moflex);
1136 static int get_index(int x)
1138 return x == 16 ? 0 : x == 8 ? 1 : x == 4 ? 2 : x == 2 ? 3 : 0;
1141 static int predict_motion(AVCodecContext *avctx,
1142 int width, int height, int index,
1143 int offsetm, int offsetx, int offsety)
1145 MobiClipContext *s = avctx->priv_data;
1146 MotionXY *motion = s->motion;
1147 GetBitContext *gb = &s->gb;
1148 int fheight = avctx->height;
1149 int fwidth = avctx->width;
1152 int sidx = -FFMAX(1, index) + s->current_pic;
1153 MotionXY mv = s->motion[0];
1159 mv.x = mv.x + get_se_golomb(gb);
1160 mv.y = mv.y + get_se_golomb(gb);
1163 motion[offsetm].x = mv.x;
1164 motion[offsetm].y = mv.y;
1166 for (int i = 0; i < 3; i++) {
1167 int method, src_linesize, dst_linesize;
1171 offsetx = offsetx >> 1;
1172 offsety = offsety >> 1;
1176 height = height >> 1;
1177 fwidth = fwidth >> 1;
1178 fheight = fheight >> 1;
1181 av_assert0(s->pic[sidx]);
1182 av_assert0(s->pic[s->current_pic]);
1183 av_assert0(s->pic[s->current_pic]->data[i]);
1184 if (!s->pic[sidx]->data[i])
1185 return AVERROR_INVALIDDATA;
1187 method = (mv.x & 1) | ((mv.y & 1) << 1);
1188 src_linesize = s->pic[sidx]->linesize[i];
1189 dst_linesize = s->pic[s->current_pic]->linesize[i];
1190 dst = s->pic[s->current_pic]->data[i] + offsetx + offsety * dst_linesize;
1194 if (offsety + (mv.y >> 1) < 0 ||
1195 offsety + (mv.y >> 1) >= fheight ||
1196 offsetx + (mv.x >> 1) < 0 ||
1197 offsetx + (mv.x >> 1) >= fwidth)
1198 return AVERROR_INVALIDDATA;
1200 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1201 (offsety + (mv.y >> 1)) * src_linesize;
1202 for (int y = 0; y < height; y++) {
1203 for (int x = 0; x < width; x++)
1205 dst += dst_linesize;
1206 src += src_linesize;
1210 if (offsety + (mv.y >> 1) < 0 ||
1211 offsety + (mv.y >> 1) >= fheight ||
1212 offsetx + (mv.x >> 1) < 0 ||
1213 offsetx + (mv.x >> 1) >= fwidth)
1214 return AVERROR_INVALIDDATA;
1216 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1217 (offsety + (mv.y >> 1)) * src_linesize;
1218 for (int y = 0; y < height; y++) {
1219 for (int x = 0; x < width; x++) {
1220 dst[x] = (uint8_t)((src[x] >> 1) + (src[x + 1] >> 1));
1223 dst += dst_linesize;
1224 src += src_linesize;
1228 if (offsety + (mv.y >> 1) < 0 ||
1229 offsety + (mv.y >> 1) >= fheight - 1 ||
1230 offsetx + (mv.x >> 1) < 0 ||
1231 offsetx + (mv.x >> 1) >= fwidth)
1232 return AVERROR_INVALIDDATA;
1234 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1235 (offsety + (mv.y >> 1)) * src_linesize;
1236 for (int y = 0; y < height; y++) {
1237 for (int x = 0; x < width; x++) {
1238 dst[x] = (uint8_t)((src[x] >> 1) + (src[x + src_linesize] >> 1));
1241 dst += dst_linesize;
1242 src += src_linesize;
1246 if (offsety + (mv.y >> 1) < 0 ||
1247 offsety + (mv.y >> 1) >= fheight - 1 ||
1248 offsetx + (mv.x >> 1) < 0 ||
1249 offsetx + (mv.x >> 1) >= fwidth)
1250 return AVERROR_INVALIDDATA;
1252 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1253 (offsety + (mv.y >> 1)) * src_linesize;
1254 for (int y = 0; y < height; y++) {
1255 for (int x = 0; x < width; x++) {
1256 dst[x] = (uint8_t)((((src[x] >> 1) + (src[x + 1] >> 1)) >> 1) +
1257 (((src[x + src_linesize] >> 1) + (src[x + 1 + src_linesize] >> 1)) >> 1));
1260 dst += dst_linesize;
1261 src += src_linesize;
1268 int adjx = index == 8 ? 0 : width / 2;
1269 int adjy = index == 8 ? height / 2 : 0;
1271 width = width - adjx;
1272 height = height - adjy;
1273 tidx = get_index(height) * 4 + get_index(width);
1275 for (int i = 0; i < 2; i++) {
1278 idx2 = get_vlc2(gb, s->mv_vlc[s->moflex][tidx].table,
1279 s->mv_vlc[s->moflex][tidx].bits, 1);
1281 return AVERROR_INVALIDDATA;
1283 ret = predict_motion(avctx, width, height, idx2,
1284 offsetm, offsetx + i * adjx, offsety + i * adjy);
1293 static int mobiclip_decode(AVCodecContext *avctx, void *data,
1294 int *got_frame, AVPacket *pkt)
1296 MobiClipContext *s = avctx->priv_data;
1297 GetBitContext *gb = &s->gb;
1298 AVFrame *frame = s->pic[s->current_pic];
1301 av_fast_padded_malloc(&s->bitstream, &s->bitstream_size,
1304 if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0)
1307 s->bdsp.bswap16_buf((uint16_t *)s->bitstream,
1308 (uint16_t *)pkt->data,
1309 (pkt->size + 1) >> 1);
1311 ret = init_get_bits8(gb, s->bitstream, s->bitstream_size);
1315 if (get_bits1(gb)) {
1316 frame->pict_type = AV_PICTURE_TYPE_I;
1317 frame->key_frame = 1;
1318 s->moflex = get_bits1(gb);
1319 s->dct_tab_idx = get_bits1(gb);
1321 ret = setup_qtables(avctx, get_bits(gb, 6));
1325 for (int y = 0; y < avctx->height; y += 16) {
1326 for (int x = 0; x < avctx->width; x += 16) {
1327 ret = decode_macroblock(avctx, frame, x, y, get_bits1(gb));
1333 MotionXY *motion = s->motion;
1335 memset(motion, 0, s->motion_size);
1337 frame->pict_type = AV_PICTURE_TYPE_P;
1338 frame->key_frame = 0;
1341 ret = setup_qtables(avctx, s->quantizer + get_se_golomb(gb));
1345 for (int y = 0; y < avctx->height; y += 16) {
1346 for (int x = 0; x < avctx->width; x += 16) {
1349 motion[0].x = mid_pred(motion[x / 16 + 1].x, motion[x / 16 + 2].x, motion[x / 16 + 3].x);
1350 motion[0].y = mid_pred(motion[x / 16 + 1].y, motion[x / 16 + 2].y, motion[x / 16 + 3].y);
1351 motion[x / 16 + 2].x = 0;
1352 motion[x / 16 + 2].y = 0;
1354 idx = get_vlc2(gb, s->mv_vlc[s->moflex][0].table,
1355 s->mv_vlc[s->moflex][0].bits, 1);
1357 return AVERROR_INVALIDDATA;
1359 if (idx == 6 || idx == 7) {
1360 ret = decode_macroblock(avctx, frame, x, y, idx == 7);
1365 ret = predict_motion(avctx, 16, 16, idx, x / 16 + 2, x, y);
1368 idx2 = get_ue_golomb(gb);
1369 if (idx2 >= FF_ARRAY_ELEMS(pframe_block8x8_coefficients_tab))
1370 return AVERROR_INVALIDDATA;
1371 flags = pframe_block8x8_coefficients_tab[idx2];
1373 for (int sy = y; sy < y + 16; sy += 8) {
1374 for (int sx = x; sx < x + 16; sx += 8) {
1376 add_pframe_coefficients(avctx, frame, sx, sy, 8, 0);
1382 add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 1 + !s->moflex);
1385 add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 2 - !s->moflex);
1392 avctx->colorspace = AVCOL_SPC_YCGCO;
1394 s->current_pic = (s->current_pic + 1) % 6;
1395 ret = av_frame_ref(data, frame);
1403 static void mobiclip_flush(AVCodecContext *avctx)
1405 MobiClipContext *s = avctx->priv_data;
1407 for (int i = 0; i < 6; i++)
1408 av_frame_unref(s->pic[i]);
1411 static av_cold int mobiclip_close(AVCodecContext *avctx)
1413 MobiClipContext *s = avctx->priv_data;
1415 ff_free_vlc(&s->vlc[0]);
1416 ff_free_vlc(&s->vlc[1]);
1418 for (int i = 0; i < 16; i++) {
1419 ff_free_vlc(&s->mv_vlc[0][i]);
1420 ff_free_vlc(&s->mv_vlc[1][i]);
1423 av_freep(&s->bitstream);
1424 s->bitstream_size = 0;
1425 av_freep(&s->motion);
1428 for (int i = 0; i < 6; i++) {
1429 av_frame_free(&s->pic[i]);
1435 AVCodec ff_mobiclip_decoder = {
1437 .long_name = NULL_IF_CONFIG_SMALL("MobiClip Video"),
1438 .type = AVMEDIA_TYPE_VIDEO,
1439 .id = AV_CODEC_ID_MOBICLIP,
1440 .priv_data_size = sizeof(MobiClipContext),
1441 .init = mobiclip_init,
1442 .decode = mobiclip_decode,
1443 .flush = mobiclip_flush,
1444 .close = mobiclip_close,
1445 .capabilities = AV_CODEC_CAP_DR1,
1446 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,