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 uint8_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 {
324 BswapDSPContext bdsp;
327 static VLC rl_vlc[2];
328 static VLC mv_vlc[2][16];
330 static av_cold int mobiclip_init(AVCodecContext *avctx)
332 MobiClipContext *s = avctx->priv_data;
334 if (avctx->width & 15 || avctx->height & 15) {
335 av_log(avctx, AV_LOG_ERROR, "width/height not multiple of 16\n");
336 return AVERROR_INVALIDDATA;
339 ff_bswapdsp_init(&s->bdsp);
341 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
343 s->motion = av_calloc(avctx->width / 16 + 3, sizeof(MotionXY));
345 return AVERROR(ENOMEM);
346 s->motion_size = (avctx->width / 16 + 3) * sizeof(MotionXY);
348 for (int i = 0; i < 6; i++) {
349 s->pic[i] = av_frame_alloc();
351 return AVERROR(ENOMEM);
354 INIT_VLC_SPARSE_STATIC(&rl_vlc[0], MOBI_RL_VLC_BITS, 104,
355 bits0, sizeof(*bits0), sizeof(*bits0),
356 codes0, sizeof(*codes0), sizeof(*codes0),
357 syms0, sizeof(*syms0), sizeof(*syms0),
358 1 << MOBI_RL_VLC_BITS);
359 INIT_VLC_SPARSE_STATIC(&rl_vlc[1], MOBI_RL_VLC_BITS, 104,
360 bits0, sizeof(*bits0), sizeof(*bits0),
361 codes0, sizeof(*codes0), sizeof(*codes0),
362 syms1, sizeof(*syms1), sizeof(*syms1),
363 1 << MOBI_RL_VLC_BITS);
364 for (int j = 0; j < 16; j++) {
365 static VLC_TYPE vlc_buf[2 * 16 << MOBI_MV_VLC_BITS][2];
366 mv_vlc[0][j].table = &vlc_buf[2 * j << MOBI_MV_VLC_BITS];
367 mv_vlc[0][j].table_allocated = 1 << MOBI_MV_VLC_BITS;
368 ff_init_vlc_sparse(&mv_vlc[0][j], MOBI_MV_VLC_BITS, mv_len[j],
369 mv_bits_mods[j], sizeof(*mv_bits_mods[j]), sizeof(*mv_bits_mods[j]),
370 mv_codes_mods[j], sizeof(*mv_codes_mods[j]), sizeof(*mv_codes_mods[j]),
371 mv_syms_mods[j], sizeof(*mv_syms_mods[j]), sizeof(*mv_syms_mods[j]), INIT_VLC_USE_NEW_STATIC);
372 mv_vlc[1][j].table = &vlc_buf[(2 * j + 1) << MOBI_MV_VLC_BITS];
373 mv_vlc[1][j].table_allocated = 1 << MOBI_MV_VLC_BITS;
374 ff_init_vlc_sparse(&mv_vlc[1][j], MOBI_MV_VLC_BITS, 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]), INIT_VLC_USE_NEW_STATIC);
383 static int setup_qtables(AVCodecContext *avctx, int quantizer)
385 MobiClipContext *s = avctx->priv_data;
388 if (quantizer < 12 || quantizer > 161)
389 return AVERROR_INVALIDDATA;
391 s->quantizer = quantizer;
396 for (int i = 0; i < 16; i++)
397 s->qtab[0][i] = quant4x4_tab[qx][i] << qy;
399 for (int i = 0; i < 64; i++)
400 s->qtab[1][i] = quant8x8_tab[qx][i] << (qy - 2);
402 for (int i = 0; i < 20; i++)
408 static void inverse4(unsigned *rs)
410 unsigned a = rs[0] + rs[2];
411 unsigned b = rs[0] - rs[2];
412 unsigned c = rs[1] + ((int)rs[3] >> 1);
413 unsigned d = ((int)rs[1] >> 1) - rs[3];
421 static void idct(int *arr, int size)
424 unsigned x3, x2, x1, x0;
439 e = (unsigned)arr[7] + arr[1] - arr[3] - (arr[3] >> 1);
440 f = (unsigned)arr[7] - arr[1] + arr[5] + (arr[5] >> 1);
441 g = (unsigned)arr[5] - arr[3] - arr[7] - (arr[7] >> 1);
442 h = (unsigned)arr[5] + arr[3] + arr[1] + (arr[1] >> 1);
443 x3 = (unsigned)g + (h >> 2);
444 x2 = (unsigned)e + (f >> 2);
445 x1 = (e >> 2) - (unsigned)f;
446 x0 = (unsigned)h - (g >> 2);
448 arr[0] = tmp[0] + x0;
449 arr[1] = tmp[1] + x1;
450 arr[2] = tmp[2] + x2;
451 arr[3] = tmp[3] + x3;
452 arr[4] = tmp[3] - x3;
453 arr[5] = tmp[2] - x2;
454 arr[6] = tmp[1] - x1;
455 arr[7] = tmp[0] - x0;
458 static void read_run_encoding(AVCodecContext *avctx,
459 int *last, int *run, int *level)
461 MobiClipContext *s = avctx->priv_data;
462 GetBitContext *gb = &s->gb;
463 int n = get_vlc2(gb, rl_vlc[s->dct_tab_idx].table,
464 MOBI_RL_VLC_BITS, 1);
466 *last = (n >> 11) == 1;
467 *run = (n >> 5) & 0x3F;
471 static int add_coefficients(AVCodecContext *avctx, AVFrame *frame,
472 int bx, int by, int size, int plane)
474 MobiClipContext *s = avctx->priv_data;
475 GetBitContext *gb = &s->gb;
477 const uint8_t *ztab = size == 8 ? ff_zigzag_direct : zigzag4x4_tab;
478 const int *qtab = s->qtab[size == 8];
479 uint8_t *dst = frame->data[plane] + by * frame->linesize[plane] + bx;
481 for (int pos = 0; get_bits_left(gb) > 0; pos++) {
482 int qval, last, run, level;
484 read_run_encoding(avctx, &last, &run, &level);
489 } else if (!get_bits1(gb)) {
490 read_run_encoding(avctx, &last, &run, &level);
491 level += run_residue[s->dct_tab_idx][(last ? 64 : 0) + run];
494 } else if (!get_bits1(gb)) {
495 read_run_encoding(avctx, &last, &run, &level);
496 run += run_residue[s->dct_tab_idx][128 + (last ? 64 : 0) + level];
500 last = get_bits1(gb);
501 run = get_bits(gb, 6);
502 level = get_sbits(gb, 12);
506 if (pos >= size * size)
507 return AVERROR_INVALIDDATA;
509 mat[ztab[pos]] = qval *(unsigned)level;
516 for (int y = 0; y < size; y++)
517 idct(&mat[y * size], size);
519 for (int y = 0; y < size; y++) {
520 for (int x = y + 1; x < size; x++) {
521 int a = mat[x * size + y];
522 int b = mat[y * size + x];
524 mat[y * size + x] = a;
525 mat[x * size + y] = b;
528 idct(&mat[y * size], size);
529 for (int x = 0; x < size; x++)
530 dst[x] = av_clip_uint8(dst[x] + (mat[y * size + x] >> 6));
531 dst += frame->linesize[plane];
537 static int add_pframe_coefficients(AVCodecContext *avctx, AVFrame *frame,
538 int bx, int by, int size, int plane)
540 MobiClipContext *s = avctx->priv_data;
541 GetBitContext *gb = &s->gb;
542 int ret, idx = get_ue_golomb_31(gb);
545 ret = add_coefficients(avctx, frame, bx, by, size, plane);
546 } else if ((unsigned)idx < FF_ARRAY_ELEMS(pframe_block4x4_coefficients_tab)) {
547 int flags = pframe_block4x4_coefficients_tab[idx];
549 for (int y = by; y < by + 8; y += 4) {
550 for (int x = bx; x < bx + 8; x += 4) {
552 ret = add_coefficients(avctx, frame, x, y, 4, plane);
560 ret = AVERROR_INVALIDDATA;
566 static int adjust(int x, int size)
568 return size == 16 ? (x + 1) >> 1 : x;
571 static uint8_t pget(BlockXY b)
576 if (b.x == -1 && b.y >= b.size) {
577 ret.x = -1, ret.y = b.size - 1;
578 } else if (b.x >= -1 && b.y >= -1) {
579 ret.x = b.x, ret.y = b.y;
580 } else if (b.x == -1 && b.y == -2) {
581 ret.x = 0, ret.y = -1;
582 } else if (b.x == -2 && b.y == -1) {
583 ret.x = -1, ret.y = 0;
586 y = av_clip(ret.ay + ret.y, 0, ret.h - 1);
587 x = av_clip(ret.ax + ret.x, 0, ret.w - 1);
589 return ret.block[y * ret.linesize + x];
592 static uint8_t half(int a, int b)
594 return ((a + b) + 1) / 2;
597 static uint8_t half3(int a, int b, int c)
599 return ((a + b + b + c) * 2 / 4 + 1) / 2;;
602 static uint8_t pick_above(BlockXY bxy)
609 static uint8_t pick_left(BlockXY bxy)
616 static uint8_t half_horz(BlockXY bxy)
618 BlockXY a = bxy, b = bxy, c = bxy;
623 return half3(pget(a), pget(b), pget(c));
626 static uint8_t half_vert(BlockXY bxy)
628 BlockXY a = bxy, b = bxy, c = bxy;
633 return half3(pget(a), pget(b), pget(c));
636 static uint8_t pick_4(BlockXY bxy)
640 if ((bxy.x % 2) == 0) {
646 ba.y = bxy.y + bxy.x / 2;
651 bb.y = bxy.y + bxy.x / 2 + 1;
660 ba.y = bxy.y + bxy.x / 2 + 1;
667 static uint8_t pick_5(BlockXY bxy)
680 val = half(pget(a), pget(b));
681 } else if (bxy.y == 0) {
688 } else if (bxy.x == 1) {
707 static uint8_t pick_6(BlockXY bxy)
720 val = half(pget(a), pget(b));
721 } else if (bxy.x == 0) {
728 } else if (bxy.y == 1) {
747 static uint8_t pick_7(BlockXY bxy)
776 return half3(acc1, clr, acc2);
779 static uint8_t pick_8(BlockXY bxy)
797 } else if (bxy.y == 1) {
802 } else if (bxy.x < bxy.size - 1) {
807 } else if (bxy.y % 2 == 0) {
810 ba.x = bxy.y / 2 + bxy.size - 1;
814 bb.x = bxy.y / 2 + bxy.size;
821 ba.x = bxy.y / 2 + bxy.size;
830 static void block_fill_simple(uint8_t *block, int size, int linesize, int fill)
832 for (int y = 0; y < size; y++) {
833 memset(block, fill, size);
838 static void block_fill(uint8_t *block, int size, int linesize,
839 int w, int h, int ax, int ay,
840 uint8_t (*pick)(BlockXY bxy))
846 bxy.linesize = linesize;
852 for (int y = 0; y < size; y++) {
854 for (int x = 0; x < size; x++) {
861 block[ax + x + (ay + y) * linesize] = val;
866 static int block_sum(const uint8_t *block, int w, int h, int linesize)
870 for (int y = 0; y < h; y++) {
871 for (int x = 0; x < w; x++) {
880 static int predict_intra(AVCodecContext *avctx, AVFrame *frame, int ax, int ay,
881 int pmode, int add_coeffs, int size, int plane)
883 MobiClipContext *s = avctx->priv_data;
884 GetBitContext *gb = &s->gb;
885 int w = avctx->width >> !!plane, h = avctx->height >> !!plane;
890 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_above);
893 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_left);
899 uint8_t *top = frame->data[plane] + FFMAX(ay - 1, 0) * frame->linesize[plane] + ax;
900 uint8_t *left = frame->data[plane] + ay * frame->linesize[plane] + FFMAX(ax - 1, 0);
901 int bottommost = frame->data[plane][(ay + size - 1) * frame->linesize[plane] + FFMAX(ax - 1, 0)];
902 int rightmost = frame->data[plane][FFMAX(ay - 1, 0) * frame->linesize[plane] + ax + size - 1];
903 int avg = (bottommost + rightmost + 1) / 2 + 2 * get_se_golomb(gb);
904 int r6 = adjust(avg - bottommost, size);
905 int r9 = adjust(avg - rightmost, size);
906 int shift = adjust(size, size) == 8 ? 3 : 2;
909 for (int x = 0; x < size; x++) {
911 arr1[x] = adjust(((bottommost - val) * (1 << shift)) + r6 * (x + 1), size);
914 for (int y = 0; y < size; y++) {
915 int val = left[y * frame->linesize[plane]];
916 arr2[y] = adjust(((rightmost - val) * (1 << shift)) + r9 * (y + 1), size);
919 block = frame->data[plane] + ay * frame->linesize[plane] + ax;
920 for (int y = 0; y < size; y++) {
921 for (int x = 0; x < size; x++) {
922 block[x] = (((top[x] + left[0] + ((arr1[x] * (y + 1) +
923 arr2[y] * (x + 1)) >> 2 * shift)) + 1) / 2) & 0xFF;
925 block += frame->linesize[plane];
926 left += frame->linesize[plane];
934 if (ax == 0 && ay == 0) {
936 } else if (ax >= 1 && ay >= 1) {
937 int left = block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1,
938 1, size, frame->linesize[plane]);
939 int top = block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax,
940 size, 1, frame->linesize[plane]);
942 fill = ((left + top) * 2 / (2 * size) + 1) / 2;
943 } else if (ax >= 1) {
944 fill = (block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1,
945 1, size, frame->linesize[plane]) * 2 / size + 1) / 2;
946 } else if (ay >= 1) {
947 fill = (block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax,
948 size, 1, frame->linesize[plane]) * 2 / size + 1) / 2;
953 block_fill_simple(frame->data[plane] + ay * frame->linesize[plane] + ax,
954 size, frame->linesize[plane], fill);
958 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_4);
961 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_5);
964 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_6);
967 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_7);
970 block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_8);
975 ret = add_coefficients(avctx, frame, ax, ay, size, plane);
980 static int get_prediction(AVCodecContext *avctx, int x, int y, int size)
982 MobiClipContext *s = avctx->priv_data;
983 GetBitContext *gb = &s->gb;
984 int index = (y & 0xC) | (x / 4 % 4);
986 uint8_t val = FFMIN(s->pre[index], index % 4 == 0 ? 9 : s->pre[index + 3]);
990 if (!get_bits1(gb)) {
991 int x = get_bits(gb, 3);
992 val = x + (x >= val ? 1 : 0);
995 s->pre[index + 4] = val;
997 s->pre[index + 5] = s->pre[index + 8] = s->pre[index + 9] = val;
1002 static int process_block(AVCodecContext *avctx, AVFrame *frame,
1003 int x, int y, int pmode, int has_coeffs, int plane)
1005 MobiClipContext *s = avctx->priv_data;
1006 GetBitContext *gb = &s->gb;
1011 pmode = get_prediction(avctx, x, y, 8);
1012 return predict_intra(avctx, frame, x, y, pmode, 0, 8, plane);
1015 tmp = get_ue_golomb_31(gb);
1016 if ((unsigned)tmp > FF_ARRAY_ELEMS(block4x4_coefficients_tab))
1017 return AVERROR_INVALIDDATA;
1021 pmode = get_prediction(avctx, x, y, 8);
1022 ret = predict_intra(avctx, frame, x, y, pmode, 1, 8, plane);
1024 int flags = block4x4_coefficients_tab[tmp - 1];
1026 for (int by = y; by < y + 8; by += 4) {
1027 for (int bx = x; bx < x + 8; bx += 4) {
1028 int new_pmode = pmode;
1031 new_pmode = get_prediction(avctx, bx, by, 4);
1032 ret = predict_intra(avctx, frame, bx, by, new_pmode, flags & 1, 4, plane);
1043 static int decode_macroblock(AVCodecContext *avctx, AVFrame *frame,
1044 int x, int y, int predict)
1046 MobiClipContext *s = avctx->priv_data;
1047 GetBitContext *gb = &s->gb;
1048 int flags, pmode_uv, idx = get_ue_golomb(gb);
1051 if (idx < 0 || idx >= FF_ARRAY_ELEMS(block8x8_coefficients_tab))
1052 return AVERROR_INVALIDDATA;
1054 flags = block8x8_coefficients_tab[idx];
1057 ret = process_block(avctx, frame, x, y, -1, flags & 1, 0);
1061 ret = process_block(avctx, frame, x + 8, y, -1, flags & 1, 0);
1065 ret = process_block(avctx, frame, x, y + 8, -1, flags & 1, 0);
1069 ret = process_block(avctx, frame, x + 8, y + 8, -1, flags & 1, 0);
1074 int pmode = get_bits(gb, 3);
1077 ret = predict_intra(avctx, frame, x, y, pmode, 0, 16, 0);
1083 ret = process_block(avctx, frame, x, y, pmode, flags & 1, 0);
1087 ret = process_block(avctx, frame, x + 8, y, pmode, flags & 1, 0);
1091 ret = process_block(avctx, frame, x, y + 8, pmode, flags & 1, 0);
1095 ret = process_block(avctx, frame, x + 8, y + 8, pmode, flags & 1, 0);
1101 pmode_uv = get_bits(gb, 3);
1102 if (pmode_uv == 2) {
1103 ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 1 + !s->moflex);
1106 ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 2 - !s->moflex);
1112 ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 1 + !s->moflex);
1116 ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 2 - !s->moflex);
1123 static int get_index(int x)
1125 return x == 16 ? 0 : x == 8 ? 1 : x == 4 ? 2 : x == 2 ? 3 : 0;
1128 static int predict_motion(AVCodecContext *avctx,
1129 int width, int height, int index,
1130 int offsetm, int offsetx, int offsety)
1132 MobiClipContext *s = avctx->priv_data;
1133 MotionXY *motion = s->motion;
1134 GetBitContext *gb = &s->gb;
1135 int fheight = avctx->height;
1136 int fwidth = avctx->width;
1139 int sidx = -FFMAX(1, index) + s->current_pic;
1140 MotionXY mv = s->motion[0];
1146 mv.x = mv.x + get_se_golomb(gb);
1147 mv.y = mv.y + get_se_golomb(gb);
1149 if (mv.x >= INT_MAX || mv.y >= INT_MAX)
1150 return AVERROR_INVALIDDATA;
1152 motion[offsetm].x = mv.x;
1153 motion[offsetm].y = mv.y;
1155 for (int i = 0; i < 3; i++) {
1156 int method, src_linesize, dst_linesize;
1160 offsetx = offsetx >> 1;
1161 offsety = offsety >> 1;
1165 height = height >> 1;
1166 fwidth = fwidth >> 1;
1167 fheight = fheight >> 1;
1170 av_assert0(s->pic[sidx]);
1171 av_assert0(s->pic[s->current_pic]);
1172 av_assert0(s->pic[s->current_pic]->data[i]);
1173 if (!s->pic[sidx]->data[i])
1174 return AVERROR_INVALIDDATA;
1176 method = (mv.x & 1) | ((mv.y & 1) << 1);
1177 src_linesize = s->pic[sidx]->linesize[i];
1178 dst_linesize = s->pic[s->current_pic]->linesize[i];
1179 dst = s->pic[s->current_pic]->data[i] + offsetx + offsety * dst_linesize;
1181 if (offsetx + (mv.x >> 1) < 0 ||
1182 offsety + (mv.y >> 1) < 0 ||
1183 offsetx + width + (mv.x + 1 >> 1) > fwidth ||
1184 offsety + height + (mv.y + 1 >> 1) > fheight)
1185 return AVERROR_INVALIDDATA;
1189 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1190 (offsety + (mv.y >> 1)) * src_linesize;
1191 for (int y = 0; y < height; y++) {
1192 for (int x = 0; x < width; x++)
1194 dst += dst_linesize;
1195 src += src_linesize;
1199 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1200 (offsety + (mv.y >> 1)) * src_linesize;
1201 for (int y = 0; y < height; y++) {
1202 for (int x = 0; x < width; x++) {
1203 dst[x] = (uint8_t)((src[x] >> 1) + (src[x + 1] >> 1));
1206 dst += dst_linesize;
1207 src += src_linesize;
1211 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1212 (offsety + (mv.y >> 1)) * src_linesize;
1213 for (int y = 0; y < height; y++) {
1214 for (int x = 0; x < width; x++) {
1215 dst[x] = (uint8_t)((src[x] >> 1) + (src[x + src_linesize] >> 1));
1218 dst += dst_linesize;
1219 src += src_linesize;
1223 src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1224 (offsety + (mv.y >> 1)) * src_linesize;
1225 for (int y = 0; y < height; y++) {
1226 for (int x = 0; x < width; x++) {
1227 dst[x] = (uint8_t)((((src[x] >> 1) + (src[x + 1] >> 1)) >> 1) +
1228 (((src[x + src_linesize] >> 1) + (src[x + 1 + src_linesize] >> 1)) >> 1));
1231 dst += dst_linesize;
1232 src += src_linesize;
1239 int adjx = index == 8 ? 0 : width / 2;
1240 int adjy = index == 8 ? height / 2 : 0;
1242 width = width - adjx;
1243 height = height - adjy;
1244 tidx = get_index(height) * 4 + get_index(width);
1246 for (int i = 0; i < 2; i++) {
1249 idx2 = get_vlc2(gb, mv_vlc[s->moflex][tidx].table,
1250 MOBI_MV_VLC_BITS, 1);
1252 ret = predict_motion(avctx, width, height, idx2,
1253 offsetm, offsetx + i * adjx, offsety + i * adjy);
1262 static int mobiclip_decode(AVCodecContext *avctx, void *data,
1263 int *got_frame, AVPacket *pkt)
1265 MobiClipContext *s = avctx->priv_data;
1266 GetBitContext *gb = &s->gb;
1267 AVFrame *frame = s->pic[s->current_pic];
1270 av_fast_padded_malloc(&s->bitstream, &s->bitstream_size,
1273 if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0)
1276 s->bdsp.bswap16_buf((uint16_t *)s->bitstream,
1277 (uint16_t *)pkt->data,
1278 (pkt->size + 1) >> 1);
1280 ret = init_get_bits8(gb, s->bitstream, FFALIGN(pkt->size, 2));
1284 if (get_bits1(gb)) {
1285 frame->pict_type = AV_PICTURE_TYPE_I;
1286 frame->key_frame = 1;
1287 s->moflex = get_bits1(gb);
1288 s->dct_tab_idx = get_bits1(gb);
1290 ret = setup_qtables(avctx, get_bits(gb, 6));
1294 for (int y = 0; y < avctx->height; y += 16) {
1295 for (int x = 0; x < avctx->width; x += 16) {
1296 ret = decode_macroblock(avctx, frame, x, y, get_bits1(gb));
1302 MotionXY *motion = s->motion;
1304 memset(motion, 0, s->motion_size);
1306 frame->pict_type = AV_PICTURE_TYPE_P;
1307 frame->key_frame = 0;
1310 ret = setup_qtables(avctx, s->quantizer + get_se_golomb(gb));
1314 for (int y = 0; y < avctx->height; y += 16) {
1315 for (int x = 0; x < avctx->width; x += 16) {
1318 motion[0].x = mid_pred(motion[x / 16 + 1].x, motion[x / 16 + 2].x, motion[x / 16 + 3].x);
1319 motion[0].y = mid_pred(motion[x / 16 + 1].y, motion[x / 16 + 2].y, motion[x / 16 + 3].y);
1320 motion[x / 16 + 2].x = 0;
1321 motion[x / 16 + 2].y = 0;
1323 idx = get_vlc2(gb, mv_vlc[s->moflex][0].table,
1324 MOBI_MV_VLC_BITS, 1);
1326 if (idx == 6 || idx == 7) {
1327 ret = decode_macroblock(avctx, frame, x, y, idx == 7);
1332 ret = predict_motion(avctx, 16, 16, idx, x / 16 + 2, x, y);
1335 idx2 = get_ue_golomb(gb);
1336 if (idx2 >= FF_ARRAY_ELEMS(pframe_block8x8_coefficients_tab))
1337 return AVERROR_INVALIDDATA;
1338 flags = pframe_block8x8_coefficients_tab[idx2];
1340 for (int sy = y; sy < y + 16; sy += 8) {
1341 for (int sx = x; sx < x + 16; sx += 8) {
1343 add_pframe_coefficients(avctx, frame, sx, sy, 8, 0);
1349 add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 1 + !s->moflex);
1352 add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 2 - !s->moflex);
1359 avctx->colorspace = AVCOL_SPC_YCGCO;
1361 s->current_pic = (s->current_pic + 1) % 6;
1362 ret = av_frame_ref(data, frame);
1370 static void mobiclip_flush(AVCodecContext *avctx)
1372 MobiClipContext *s = avctx->priv_data;
1374 for (int i = 0; i < 6; i++)
1375 av_frame_unref(s->pic[i]);
1378 static av_cold int mobiclip_close(AVCodecContext *avctx)
1380 MobiClipContext *s = avctx->priv_data;
1382 av_freep(&s->bitstream);
1383 s->bitstream_size = 0;
1384 av_freep(&s->motion);
1387 for (int i = 0; i < 6; i++) {
1388 av_frame_free(&s->pic[i]);
1394 AVCodec ff_mobiclip_decoder = {
1396 .long_name = NULL_IF_CONFIG_SMALL("MobiClip Video"),
1397 .type = AVMEDIA_TYPE_VIDEO,
1398 .id = AV_CODEC_ID_MOBICLIP,
1399 .priv_data_size = sizeof(MobiClipContext),
1400 .init = mobiclip_init,
1401 .decode = mobiclip_decode,
1402 .flush = mobiclip_flush,
1403 .close = mobiclip_close,
1404 .capabilities = AV_CODEC_CAP_DR1,
1405 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,