FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/mobiclip.c
Date: 2026-09-25 07:50:45
Exec Total Coverage
Lines: 0 675 0.0%
Functions: 0 33 0.0%
Branches: 0 357 0.0%

Line Branch Exec Source
1 /*
2 * MobiClip Video decoder
3 * Copyright (c) 2015-2016 Florian Nouwt
4 * Copyright (c) 2017 Adib Surani
5 * Copyright (c) 2020 Paul B Mahol
6 *
7 * This file is part of FFmpeg.
8 *
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #include <inttypes.h>
25
26 #include "libavutil/attributes.h"
27 #include "libavutil/avassert.h"
28 #include "libavutil/mem.h"
29 #include "libavutil/thread.h"
30
31 #include "avcodec.h"
32 #include "bswapdsp.h"
33 #include "codec_internal.h"
34 #include "decode.h"
35 #include "get_bits.h"
36 #include "golomb.h"
37 #include "mathops.h"
38
39 #define MOBI_RL_VLC_BITS 12
40 #define MOBI_MV_VLC_BITS 6
41
42 static const uint8_t zigzag4x4_tab[] =
43 {
44 0x00, 0x04, 0x01, 0x02, 0x05, 0x08, 0x0C, 0x09, 0x06, 0x03, 0x07, 0x0A,
45 0x0D, 0x0E, 0x0B, 0x0F
46 };
47
48 static const uint8_t quant4x4_tab[][16] =
49 {
50 { 10, 13, 13, 10, 16, 10, 13, 13, 13, 13, 16, 10, 16, 13, 13, 16 },
51 { 11, 14, 14, 11, 18, 11, 14, 14, 14, 14, 18, 11, 18, 14, 14, 18 },
52 { 13, 16, 16, 13, 20, 13, 16, 16, 16, 16, 20, 13, 20, 16, 16, 20 },
53 { 14, 18, 18, 14, 23, 14, 18, 18, 18, 18, 23, 14, 23, 18, 18, 23 },
54 { 16, 20, 20, 16, 25, 16, 20, 20, 20, 20, 25, 16, 25, 20, 20, 25 },
55 { 18, 23, 23, 18, 29, 18, 23, 23, 23, 23, 29, 18, 29, 23, 23, 29 },
56 };
57
58 static const uint8_t quant8x8_tab[][64] =
59 {
60 { 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,
61 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,},
62 { 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,
63 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,},
64 { 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,
65 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,},
66 { 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,
67 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,},
68 { 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,
69 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,},
70 { 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,
71 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,},
72 };
73
74 static const uint8_t block4x4_coefficients_tab[] =
75 {
76 15, 0, 2, 1, 4, 8, 12, 3, 11, 13, 14, 7, 10, 5, 9, 6,
77 };
78
79 static const uint8_t pframe_block4x4_coefficients_tab[] =
80 {
81 0, 4, 1, 8, 2, 12, 3, 5, 10, 15, 7, 13, 14, 11, 9, 6,
82 };
83
84 static const uint8_t block8x8_coefficients_tab[] =
85 {
86 0x00, 0x1F, 0x3F, 0x0F, 0x08, 0x04, 0x02, 0x01, 0x0B, 0x0E, 0x1B, 0x0D,
87 0x03, 0x07, 0x0C, 0x17, 0x1D, 0x0A, 0x1E, 0x05, 0x10, 0x2F, 0x37, 0x3B,
88 0x13, 0x3D, 0x3E, 0x09, 0x1C, 0x06, 0x15, 0x1A, 0x33, 0x11, 0x12, 0x14,
89 0x18, 0x20, 0x3C, 0x35, 0x19, 0x16, 0x3A, 0x30, 0x31, 0x32, 0x27, 0x34,
90 0x2B, 0x2D, 0x39, 0x38, 0x23, 0x36, 0x2E, 0x21, 0x25, 0x22, 0x24, 0x2C,
91 0x2A, 0x28, 0x29, 0x26,
92 };
93
94 static const uint8_t pframe_block8x8_coefficients_tab[] =
95 {
96 0x00, 0x0F, 0x04, 0x01, 0x08, 0x02, 0x0C, 0x03, 0x05, 0x0A, 0x0D, 0x07, 0x0E, 0x0B, 0x1F, 0x09,
97 0x06, 0x10, 0x3F, 0x1E, 0x17, 0x1D, 0x1B, 0x1C, 0x13, 0x18, 0x1A, 0x12, 0x11, 0x14, 0x15, 0x20,
98 0x2F, 0x16, 0x19, 0x37, 0x3D, 0x3E, 0x3B, 0x3C, 0x33, 0x35, 0x21, 0x24, 0x22, 0x28, 0x23, 0x2C,
99 0x30, 0x27, 0x2D, 0x25, 0x3A, 0x2B, 0x2E, 0x2A, 0x31, 0x34, 0x38, 0x32, 0x29, 0x26, 0x39, 0x36
100 };
101
102 static const uint8_t run_residue[2][256] =
103 {
104 {
105 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,
106 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,
107 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,
108 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,
109 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,
110 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,
111 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,
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 },
114 {
115 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,
116 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,
117 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,
118 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,
119 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,
120 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 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,
122 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,
123 },
124 };
125
126 static const uint8_t bits0[] = {
127 9, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
128 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12,
129 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 10, 10, 9,
130 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
131 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
132 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6,
133 6, 6, 6, 6, 6, 6, 5, 5, 5, 4, 2, 3, 4, 4,
134 };
135
136 static const uint16_t syms0[] = {
137 0x0, 0x822, 0x803, 0xB, 0xA, 0xB81, 0xB61, 0xB41, 0xB21, 0x122,
138 0x102, 0xE2, 0xC2, 0xA2, 0x63, 0x43, 0x24, 0xC, 0x25, 0x2E1, 0x301,
139 0xBA1, 0xBC1, 0xBE1, 0xC01, 0x26, 0x44, 0x83, 0xA3, 0xC3, 0x142,
140 0x321, 0x341, 0xC21, 0xC41, 0xC61, 0xC81, 0xCA1, 0xCC1, 0xCE1, 0xD01,
141 0x0, 0x9, 0x8, 0xB01, 0xAE1, 0xAC1, 0xAA1, 0xA81, 0xA61, 0xA41, 0xA21,
142 0x802, 0x2C1, 0x2A1, 0x281, 0x261, 0x241, 0x221, 0x201, 0x1E1, 0x82,
143 0x62, 0x7, 0x6, 0xA01, 0x9E1, 0x9C1, 0x9A1, 0x981, 0x961, 0x941, 0x921,
144 0x1C1, 0x1A1, 0x42, 0x23, 0x5, 0x901, 0x8E1, 0x8C1, 0x8A1, 0x181, 0x161,
145 0x141, 0x4, 0x881, 0x861, 0x841, 0x821, 0x121, 0x101, 0xE1, 0xC1, 0x22,
146 0x3, 0xA1, 0x81, 0x61, 0x801, 0x1, 0x21, 0x41, 0x2,
147 };
148
149 static const uint16_t syms1[] = {
150 0x0, 0x807, 0x806, 0x16, 0x15, 0x842, 0x823, 0x805, 0x1A1, 0xA3, 0x102, 0x83,
151 0x64, 0x44, 0x27, 0x14, 0x13, 0x17, 0x18, 0x28, 0x122, 0x862, 0x882, 0x9E1, 0xA01,
152 0x19, 0x1A, 0x1B, 0x29, 0xC3, 0x2A, 0x45, 0xE3, 0x1C1, 0x808, 0x8A2, 0x8C2, 0xA21,
153 0xA41, 0xA61, 0xA81, 0x0, 0x12, 0x11, 0x9C1, 0x9A1, 0x981, 0x961, 0x941, 0x822, 0x804,
154 0x181, 0x161, 0xE2, 0xC2, 0xA2, 0x63, 0x43, 0x26, 0x25, 0x10, 0x82, 0xF, 0xE, 0xD, 0x901,
155 0x8E1, 0x8C1, 0x803, 0x141, 0x121, 0x101, 0x921, 0x62, 0x24, 0xC, 0xB, 0xA, 0x881, 0x861,
156 0xC1, 0x8A1, 0xE1, 0x42, 0x23, 0x9, 0x802, 0xA1, 0x841, 0x821, 0x81, 0x61, 0x8, 0x7, 0x22,
157 0x6, 0x41, 0x5, 0x4, 0x801, 0x1, 0x2, 0x21, 0x3,
158 };
159
160 static const uint8_t mv_len[16] =
161 {
162 10, 8, 8, 7, 8, 8, 8, 7, 8, 8, 8, 7, 7, 7, 7, 6,
163 };
164
165 static const uint8_t mv_bits[2][16][10] =
166 {
167 {
168 { 2, 3, 3, 5, 5, 4, 4, 5, 5, 2 },
169 { 2, 3, 4, 4, 3, 4, 4, 2 },
170 { 3, 4, 4, 2, 4, 4, 3, 2 },
171 { 1, 3, 4, 5, 5, 3, 3 },
172 { 2, 4, 4, 3, 3, 4, 4, 2 },
173 { 2, 3, 4, 4, 4, 4, 3, 2 },
174 { 2, 3, 4, 4, 4, 4, 3, 2 },
175 { 2, 2, 3, 4, 5, 5, 2 },
176 { 2, 3, 4, 4, 3, 4, 4, 2 },
177 { 2, 4, 4, 3, 4, 4, 3, 2 },
178 { 2, 3, 3, 5, 5, 4, 3, 2 },
179 { 2, 3, 4, 4, 3, 3, 2 },
180 { 1, 4, 4, 3, 3, 4, 4 },
181 { 2, 3, 4, 4, 3, 3, 2 },
182 { 2, 3, 4, 4, 3, 3, 2 },
183 { 3, 3, 2, 2, 3, 3 },
184 },
185 {
186 { 3, 4, 5, 5, 3, 5, 6, 6, 4, 1 },
187 { 2, 3, 4, 5, 5, 2, 3, 3 },
188 { 2, 4, 4, 3, 3, 4, 4, 2 },
189 { 1, 4, 4, 3, 4, 4, 3 },
190 { 3, 3, 2, 4, 5, 5, 3, 2 },
191 { 3, 4, 4, 3, 3, 3, 3, 2 },
192 { 1, 3, 3, 4, 4, 4, 5, 5 },
193 { 1, 4, 4, 3, 3, 4, 4 },
194 { 2, 4, 4, 3, 3, 4, 4, 2 },
195 { 1, 3, 3, 4, 4, 4, 5, 5 },
196 { 2, 3, 4, 4, 4, 4, 3, 2 },
197 { 2, 3, 3, 4, 4, 3, 2 },
198 { 1, 4, 4, 3, 3, 4, 4 },
199 { 1, 4, 4, 3, 3, 4, 4 },
200 { 2, 3, 3, 4, 4, 3, 2 },
201 { 2, 3, 3, 3, 3, 2 },
202 }
203 };
204
205 static const uint8_t mv_syms[2][16][10] =
206 {
207 {
208 { 1, 8, 9, 4, 3, 2, 7, 5, 6, 0 },
209 { 0, 9, 5, 4, 2, 3, 8, 1 },
210 { 3, 9, 5, 0, 4, 8, 2, 1 },
211 { 1, 3, 4, 8, 5, 2, 0 },
212 { 0, 5, 4, 8, 2, 3, 9, 1 },
213 { 0, 3, 5, 9, 4, 8, 2, 1 },
214 { 0, 3, 9, 5, 8, 4, 2, 1 },
215 { 0, 2, 3, 4, 8, 5, 1 },
216 { 0, 3, 8, 4, 2, 5, 9, 1 },
217 { 2, 8, 9, 3, 5, 4, 0, 1 },
218 { 0, 4, 3, 8, 9, 5, 2, 1 },
219 { 0, 4, 8, 5, 3, 2, 1 },
220 { 1, 9, 4, 2, 0, 5, 3 },
221 { 2, 4, 9, 5, 3, 0, 1 },
222 { 0, 4, 9, 5, 3, 2, 1 },
223 { 5, 4, 1, 0, 3, 2 },
224 },
225 {
226 { 8, 2, 3, 6, 1, 7, 5, 4, 9, 0 },
227 { 9, 2, 3, 5, 4, 1, 8, 0 },
228 { 0, 5, 4, 2, 9, 3, 8, 1 },
229 { 1, 5, 4, 2, 8, 3, 0 },
230 { 2, 9, 8, 3, 5, 4, 0, 1 },
231 { 3, 5, 4, 2, 9, 8, 0, 1 },
232 { 1, 2, 0, 9, 8, 3, 5, 4 },
233 { 1, 8, 5, 2, 0, 4, 3 },
234 { 0, 5, 4, 2, 8, 3, 9, 1 },
235 { 1, 2, 0, 9, 8, 3, 5, 4 },
236 { 0, 3, 9, 8, 5, 4, 2, 1 },
237 { 0, 4, 3, 8, 5, 2, 1 },
238 { 1, 5, 4, 2, 0, 9, 3 },
239 { 1, 9, 5, 2, 0, 4, 3 },
240 { 0, 5, 3, 9, 4, 2, 1 },
241 { 0, 4, 5, 3, 2, 1 },
242 }
243 };
244
245 typedef struct BlockXY {
246 int w, h;
247 int ax, ay;
248 int x, y;
249 int size;
250 uint8_t *block;
251 int linesize;
252 } BlockXY;
253
254 typedef struct MotionXY {
255 int x, y;
256 } MotionXY;
257
258 typedef struct MobiClipContext {
259 AVFrame *pic[6];
260
261 int current_pic;
262 int moflex;
263 int dct_tab_idx;
264 int quantizer;
265
266 GetBitContext gb;
267
268 uint8_t *bitstream;
269 int bitstream_size;
270
271 int qtab[2][64];
272 uint8_t pre[32];
273 MotionXY *motion;
274 int motion_size;
275
276 BswapDSPContext bdsp;
277 } MobiClipContext;
278
279 static const VLCElem *rl_vlc[2];
280 static const VLCElem *mv_vlc[2][16];
281
282 ✗ static av_cold void mobiclip_init_static(void)
283 {
284 static VLCElem vlc_buf[(2 << MOBI_RL_VLC_BITS) + (2 * 16 << MOBI_MV_VLC_BITS)];
285 ✗ VLCInitState state =VLC_INIT_STATE(vlc_buf);
286
287 ✗ for (int i = 0; i < 2; i++) {
288 ✗ rl_vlc[i] =
289 ✗ ff_vlc_init_tables_from_lengths(&state, MOBI_RL_VLC_BITS, 104,
290 bits0, sizeof(*bits0),
291 i ? syms1 : syms0, sizeof(*syms0), sizeof(*syms0),
292 0, 0);
293 ✗ for (int j = 0; j < 16; j++) {
294 ✗ mv_vlc[i][j] =
295 ✗ ff_vlc_init_tables_from_lengths(&state, MOBI_MV_VLC_BITS, mv_len[j],
296 ✗ mv_bits[i][j], sizeof(*mv_bits[i][j]),
297 ✗ mv_syms[i][j], sizeof(*mv_syms[i][j]), sizeof(*mv_syms[i][j]),
298 0, 0);
299 }
300 }
301 ✗ }
302
303 ✗ static av_cold int mobiclip_init(AVCodecContext *avctx)
304 {
305 static AVOnce init_static_once = AV_ONCE_INIT;
306 ✗ MobiClipContext *s = avctx->priv_data;
307
308 ✗ if (avctx->width & 15 || avctx->height & 15) {
309 ✗ av_log(avctx, AV_LOG_ERROR, "width/height not multiple of 16\n");
310 ✗ return AVERROR_INVALIDDATA;
311 }
312
313 ✗ ff_bswapdsp_init(&s->bdsp);
314
315 ✗ avctx->pix_fmt = AV_PIX_FMT_YUV420P;
316
317 ✗ s->motion = av_calloc(avctx->width / 16 + 3, sizeof(MotionXY));
318 ✗ if (!s->motion)
319 ✗ return AVERROR(ENOMEM);
320 ✗ s->motion_size = (avctx->width / 16 + 3) * sizeof(MotionXY);
321
322 ✗ for (int i = 0; i < 6; i++) {
323 ✗ s->pic[i] = av_frame_alloc();
324 ✗ if (!s->pic[i])
325 ✗ return AVERROR(ENOMEM);
326 }
327
328 ✗ ff_thread_once(&init_static_once, mobiclip_init_static);
329
330 ✗ return 0;
331 }
332
333 ✗ static int setup_qtables(AVCodecContext *avctx, int64_t quantizer)
334 {
335 ✗ MobiClipContext *s = avctx->priv_data;
336 int qx, qy;
337
338 ✗ if (quantizer < 12 || quantizer > 161)
339 ✗ return AVERROR_INVALIDDATA;
340
341 ✗ s->quantizer = quantizer;
342
343 ✗ qx = quantizer % 6;
344 ✗ qy = quantizer / 6;
345
346 ✗ for (int i = 0; i < 16; i++)
347 ✗ s->qtab[0][i] = quant4x4_tab[qx][i] << qy;
348
349 ✗ for (int i = 0; i < 64; i++)
350 ✗ s->qtab[1][i] = quant8x8_tab[qx][i] << (qy - 2);
351
352 ✗ for (int i = 0; i < 20; i++)
353 ✗ s->pre[i] = 9;
354
355 ✗ return 0;
356 }
357
358 ✗ static void inverse4(unsigned *rs)
359 {
360 ✗ unsigned a = rs[0] + rs[2];
361 ✗ unsigned b = rs[0] - rs[2];
362 ✗ unsigned c = rs[1] + ((int)rs[3] >> 1);
363 ✗ unsigned d = ((int)rs[1] >> 1) - rs[3];
364
365 ✗ rs[0] = a + c;
366 ✗ rs[1] = b + d;
367 ✗ rs[2] = b - d;
368 ✗ rs[3] = a - c;
369 ✗ }
370
371 ✗ static void idct(int *arr, int size)
372 {
373 int e, f, g, h;
374 unsigned x3, x2, x1, x0;
375 int tmp[4];
376
377 ✗ if (size == 4) {
378 ✗ inverse4(arr);
379 ✗ return;
380 }
381
382 ✗ tmp[0] = arr[0];
383 ✗ tmp[1] = arr[2];
384 ✗ tmp[2] = arr[4];
385 ✗ tmp[3] = arr[6];
386
387 ✗ inverse4(tmp);
388
389 ✗ e = (unsigned)arr[7] + arr[1] - arr[3] - (arr[3] >> 1);
390 ✗ f = (unsigned)arr[7] - arr[1] + arr[5] + (arr[5] >> 1);
391 ✗ g = (unsigned)arr[5] - arr[3] - arr[7] - (arr[7] >> 1);
392 ✗ h = (unsigned)arr[5] + arr[3] + arr[1] + (arr[1] >> 1);
393 ✗ x3 = (unsigned)g + (h >> 2);
394 ✗ x2 = (unsigned)e + (f >> 2);
395 ✗ x1 = (e >> 2) - (unsigned)f;
396 ✗ x0 = (unsigned)h - (g >> 2);
397
398 ✗ arr[0] = tmp[0] + x0;
399 ✗ arr[1] = tmp[1] + x1;
400 ✗ arr[2] = tmp[2] + x2;
401 ✗ arr[3] = tmp[3] + x3;
402 ✗ arr[4] = tmp[3] - x3;
403 ✗ arr[5] = tmp[2] - x2;
404 ✗ arr[6] = tmp[1] - x1;
405 ✗ arr[7] = tmp[0] - x0;
406 }
407
408 ✗ static void read_run_encoding(AVCodecContext *avctx,
409 int *last, int *run, int *level)
410 {
411 ✗ MobiClipContext *s = avctx->priv_data;
412 ✗ GetBitContext *gb = &s->gb;
413 ✗ int n = get_vlc2(gb, rl_vlc[s->dct_tab_idx], MOBI_RL_VLC_BITS, 1);
414
415 ✗ *last = (n >> 11) == 1;
416 ✗ *run = (n >> 5) & 0x3F;
417 ✗ *level = n & 0x1F;
418 ✗ }
419
420 ✗ static int add_coefficients(AVCodecContext *avctx, AVFrame *frame,
421 int bx, int by, int size, int plane)
422 {
423 ✗ MobiClipContext *s = avctx->priv_data;
424 ✗ GetBitContext *gb = &s->gb;
425 ✗ int mat[64] = { 0 };
426 ✗ const uint8_t *ztab = size == 8 ? ff_zigzag_direct : zigzag4x4_tab;
427 ✗ const int *qtab = s->qtab[size == 8];
428 ✗ uint8_t *dst = frame->data[plane] + by * frame->linesize[plane] + bx;
429
430 ✗ for (int pos = 0; get_bits_left(gb) > 0; pos++) {
431 int qval, last, run, level;
432
433 ✗ read_run_encoding(avctx, &last, &run, &level);
434
435 ✗ if (level) {
436 ✗ if (get_bits1(gb))
437 ✗ level = -level;
438 ✗ } else if (!get_bits1(gb)) {
439 ✗ read_run_encoding(avctx, &last, &run, &level);
440 ✗ level += run_residue[s->dct_tab_idx][(last ? 64 : 0) + run];
441 ✗ if (get_bits1(gb))
442 ✗ level = -level;
443 ✗ } else if (!get_bits1(gb)) {
444 ✗ read_run_encoding(avctx, &last, &run, &level);
445 ✗ run += run_residue[s->dct_tab_idx][128 + (last ? 64 : 0) + level];
446 ✗ if (get_bits1(gb))
447 ✗ level = -level;
448 } else {
449 ✗ last = get_bits1(gb);
450 ✗ run = get_bits(gb, 6);
451 ✗ level = get_sbits(gb, 12);
452 }
453
454 ✗ pos += run;
455 ✗ if (pos >= size * size)
456 ✗ return AVERROR_INVALIDDATA;
457 ✗ qval = qtab[pos];
458 ✗ mat[ztab[pos]] = qval *(unsigned)level;
459
460 ✗ if (last)
461 ✗ break;
462 }
463
464 ✗ mat[0] += 32;
465 ✗ for (int y = 0; y < size; y++)
466 ✗ idct(&mat[y * size], size);
467
468 ✗ for (int y = 0; y < size; y++) {
469 ✗ for (int x = y + 1; x < size; x++) {
470 ✗ int a = mat[x * size + y];
471 ✗ int b = mat[y * size + x];
472
473 ✗ mat[y * size + x] = a;
474 ✗ mat[x * size + y] = b;
475 }
476
477 ✗ idct(&mat[y * size], size);
478 ✗ for (int x = 0; x < size; x++)
479 ✗ dst[x] = av_clip_uint8(dst[x] + (mat[y * size + x] >> 6));
480 ✗ dst += frame->linesize[plane];
481 }
482
483 ✗ return 0;
484 }
485
486 ✗ static int add_pframe_coefficients(AVCodecContext *avctx, AVFrame *frame,
487 int bx, int by, int size, int plane)
488 {
489 ✗ MobiClipContext *s = avctx->priv_data;
490 ✗ GetBitContext *gb = &s->gb;
491 ✗ int ret, idx = get_ue_golomb_31(gb);
492
493 ✗ if (idx == 0) {
494 ✗ return add_coefficients(avctx, frame, bx, by, size, plane);
495 ✗ } else if ((unsigned)idx < FF_ARRAY_ELEMS(pframe_block4x4_coefficients_tab)) {
496 ✗ int flags = pframe_block4x4_coefficients_tab[idx];
497
498 ✗ for (int y = by; y < by + 8; y += 4) {
499 ✗ for (int x = bx; x < bx + 8; x += 4) {
500 ✗ if (flags & 1) {
501 ✗ ret = add_coefficients(avctx, frame, x, y, 4, plane);
502 ✗ if (ret < 0)
503 ✗ return ret;
504 }
505 ✗ flags >>= 1;
506 }
507 }
508 ✗ return 0;
509 } else {
510 ✗ return AVERROR_INVALIDDATA;
511 }
512 }
513
514 ✗ static int adjust(int x, int size)
515 {
516 ✗ return size == 16 ? (x + 1) >> 1 : x;
517 }
518
519 ✗ static uint8_t pget(BlockXY b)
520 {
521 ✗ BlockXY ret = b;
522 int x, y;
523
524 ✗ if (b.x == -1 && b.y >= b.size) {
525 ✗ ret.x = -1, ret.y = b.size - 1;
526 ✗ } else if (b.x >= -1 && b.y >= -1) {
527 ✗ ret.x = b.x, ret.y = b.y;
528 ✗ } else if (b.x == -1 && b.y == -2) {
529 ✗ ret.x = 0, ret.y = -1;
530 ✗ } else if (b.x == -2 && b.y == -1) {
531 ✗ ret.x = -1, ret.y = 0;
532 }
533
534 ✗ y = av_clip(ret.ay + ret.y, 0, ret.h - 1);
535 ✗ x = av_clip(ret.ax + ret.x, 0, ret.w - 1);
536
537 ✗ return ret.block[y * ret.linesize + x];
538 }
539
540 ✗ static uint8_t half(int a, int b)
541 {
542 ✗ return ((a + b) + 1) / 2;
543 }
544
545 ✗ static uint8_t half3(int a, int b, int c)
546 {
547 ✗ return ((a + b + b + c) * 2 / 4 + 1) / 2;
548 }
549
550 ✗ static uint8_t pick_above(BlockXY bxy)
551 {
552 ✗ bxy.y = bxy.y - 1;
553
554 ✗ return pget(bxy);
555 }
556
557 ✗ static uint8_t pick_left(BlockXY bxy)
558 {
559 ✗ bxy.x = bxy.x - 1;
560
561 ✗ return pget(bxy);
562 }
563
564 ✗ static uint8_t half_horz(BlockXY bxy)
565 {
566 ✗ BlockXY a = bxy, b = bxy, c = bxy;
567
568 ✗ a.x -= 1;
569 ✗ c.x += 1;
570
571 ✗ return half3(pget(a), pget(b), pget(c));
572 }
573
574 ✗ static uint8_t half_vert(BlockXY bxy)
575 {
576 ✗ BlockXY a = bxy, b = bxy, c = bxy;
577
578 ✗ a.y -= 1;
579 ✗ c.y += 1;
580
581 ✗ return half3(pget(a), pget(b), pget(c));
582 }
583
584 ✗ static uint8_t pick_4(BlockXY bxy)
585 {
586 int val;
587
588 ✗ if ((bxy.x % 2) == 0) {
589 BlockXY ba, bb;
590 int a, b;
591
592 ✗ ba = bxy;
593 ✗ ba.x = -1;
594 ✗ ba.y = bxy.y + bxy.x / 2;
595 ✗ a = pget(ba);
596
597 ✗ bb = bxy;
598 ✗ bb.x = -1;
599 ✗ bb.y = bxy.y + bxy.x / 2 + 1;
600 ✗ b = pget(bb);
601
602 ✗ val = half(a, b);
603 } else {
604 BlockXY ba;
605
606 ✗ ba = bxy;
607 ✗ ba.x = -1;
608 ✗ ba.y = bxy.y + bxy.x / 2 + 1;
609 ✗ val = half_vert(ba);
610 }
611
612 ✗ return val;
613 }
614
615 ✗ static uint8_t pick_5(BlockXY bxy)
616 {
617 int val;
618
619 ✗ if (bxy.x == 0) {
620 ✗ BlockXY a = bxy;
621 ✗ BlockXY b = bxy;
622
623 ✗ a.x = -1;
624 ✗ a.y -= 1;
625
626 ✗ b.x = -1;
627
628 ✗ val = half(pget(a), pget(b));
629 ✗ } else if (bxy.y == 0) {
630 ✗ BlockXY a = bxy;
631
632 ✗ a.x -= 2;
633 ✗ a.y -= 1;
634
635 ✗ val = half_horz(a);
636 ✗ } else if (bxy.x == 1) {
637 ✗ BlockXY a = bxy;
638
639 ✗ a.x -= 2;
640 ✗ a.y -= 1;
641
642 ✗ val = half_vert(a);
643 } else {
644 ✗ BlockXY a = bxy;
645
646 ✗ a.x -= 2;
647 ✗ a.y -= 1;
648
649 ✗ val = pget(a);
650 }
651
652 ✗ return val;
653 }
654
655 ✗ static uint8_t pick_6(BlockXY bxy)
656 {
657 int val;
658
659 ✗ if (bxy.y == 0) {
660 ✗ BlockXY a = bxy;
661 ✗ BlockXY b = bxy;
662
663 ✗ a.x -= 1;
664 ✗ a.y = -1;
665
666 ✗ b.y = -1;
667
668 ✗ val = half(pget(a), pget(b));
669 ✗ } else if (bxy.x == 0) {
670 ✗ BlockXY a = bxy;
671
672 ✗ a.x -= 1;
673 ✗ a.y -= 2;
674
675 ✗ val = half_vert(a);
676 ✗ } else if (bxy.y == 1) {
677 ✗ BlockXY a = bxy;
678
679 ✗ a.x -= 1;
680 ✗ a.y -= 2;
681
682 ✗ val = half_horz(a);
683 } else {
684 ✗ BlockXY a = bxy;
685
686 ✗ a.x -= 1;
687 ✗ a.y -= 2;
688
689 ✗ val = pget(a);
690 }
691
692 ✗ return val;
693 }
694
695 ✗ static uint8_t pick_7(BlockXY bxy)
696 {
697 int clr, acc1, acc2;
698 ✗ BlockXY a = bxy;
699
700 ✗ a.x -= 1;
701 ✗ a.y -= 1;
702 ✗ clr = pget(a);
703 ✗ if (bxy.x && bxy.y)
704 ✗ return clr;
705
706 ✗ if (bxy.x == 0) {
707 ✗ a.x = -1;
708 ✗ a.y = bxy.y;
709 } else {
710 ✗ a.x = bxy.x - 2;
711 ✗ a.y = -1;
712 }
713 ✗ acc1 = pget(a);
714
715 ✗ if (bxy.y == 0) {
716 ✗ a.x = bxy.x;
717 ✗ a.y = -1;
718 } else {
719 ✗ a.x = -1;
720 ✗ a.y = bxy.y - 2;
721 }
722 ✗ acc2 = pget(a);
723
724 ✗ return half3(acc1, clr, acc2);
725 }
726
727 ✗ static uint8_t pick_8(BlockXY bxy)
728 {
729 ✗ BlockXY ba = bxy;
730 ✗ BlockXY bb = bxy;
731 int val;
732
733 ✗ if (bxy.y == 0) {
734 int a, b;
735
736 ✗ ba.y = -1;
737 ✗ a = pget(ba);
738
739 ✗ bb.x += 1;
740 ✗ bb.y = -1;
741
742 ✗ b = pget(bb);
743
744 ✗ val = half(a, b);
745 ✗ } else if (bxy.y == 1) {
746 ✗ ba.x += 1;
747 ✗ ba.y -= 2;
748
749 ✗ val = half_horz(ba);
750 ✗ } else if (bxy.x < bxy.size - 1) {
751 ✗ ba.x += 1;
752 ✗ ba.y -= 2;
753
754 ✗ val = pget(ba);
755 ✗ } else if (bxy.y % 2 == 0) {
756 int a, b;
757
758 ✗ ba.x = bxy.y / 2 + bxy.size - 1;
759 ✗ ba.y = -1;
760 ✗ a = pget(ba);
761
762 ✗ bb.x = bxy.y / 2 + bxy.size;
763 ✗ bb.y = -1;
764
765 ✗ b = pget(bb);
766
767 ✗ val = half(a, b);
768 } else {
769 ✗ ba.x = bxy.y / 2 + bxy.size;
770 ✗ ba.y = -1;
771
772 ✗ val = half_horz(ba);
773 }
774
775 ✗ return val;
776 }
777
778 ✗ static void block_fill_simple(uint8_t *block, int size, int linesize, int fill)
779 {
780 ✗ for (int y = 0; y < size; y++) {
781 ✗ memset(block, fill, size);
782 ✗ block += linesize;
783 }
784 ✗ }
785
786 ✗ static void block_fill(uint8_t *block, int size, int linesize,
787 int w, int h, int ax, int ay,
788 uint8_t (*pick)(BlockXY bxy))
789 {
790 BlockXY bxy;
791
792 ✗ bxy.size = size;
793 ✗ bxy.block = block;
794 ✗ bxy.linesize = linesize;
795 ✗ bxy.w = w;
796 ✗ bxy.h = h;
797 ✗ bxy.ay = ay;
798 ✗ bxy.ax = ax;
799
800 ✗ for (int y = 0; y < size; y++) {
801 ✗ bxy.y = y;
802 ✗ for (int x = 0; x < size; x++) {
803 uint8_t val;
804
805 ✗ bxy.x = x;
806
807 ✗ val = pick(bxy);
808
809 ✗ block[ax + x + (ay + y) * linesize] = val;
810 }
811 }
812 ✗ }
813
814 ✗ static int block_sum(const uint8_t *block, int w, int h, int linesize)
815 {
816 ✗ int sum = 0;
817
818 ✗ for (int y = 0; y < h; y++) {
819 ✗ for (int x = 0; x < w; x++) {
820 ✗ sum += block[x];
821 }
822 ✗ block += linesize;
823 }
824
825 ✗ return sum;
826 }
827
828 ✗ static int predict_intra(AVCodecContext *avctx, AVFrame *frame, int ax, int ay,
829 int pmode, int add_coeffs, int size, int plane)
830 {
831 ✗ MobiClipContext *s = avctx->priv_data;
832 ✗ GetBitContext *gb = &s->gb;
833 ✗ int w = avctx->width >> !!plane, h = avctx->height >> !!plane;
834 ✗ int ret = 0;
835
836 ✗ switch (pmode) {
837 ✗ case 0:
838 ✗ block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_above);
839 ✗ break;
840 ✗ case 1:
841 ✗ block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_left);
842 ✗ break;
843 ✗ case 2:
844 {
845 int arr1[16];
846 int arr2[16];
847 ✗ uint8_t *top = frame->data[plane] + FFMAX(ay - 1, 0) * frame->linesize[plane] + ax;
848 ✗ uint8_t *left = frame->data[plane] + ay * frame->linesize[plane] + FFMAX(ax - 1, 0);
849 ✗ int bottommost = frame->data[plane][(ay + size - 1) * frame->linesize[plane] + FFMAX(ax - 1, 0)];
850 ✗ int rightmost = frame->data[plane][FFMAX(ay - 1, 0) * frame->linesize[plane] + ax + size - 1];
851 ✗ int avg = (bottommost + rightmost + 1) / 2 + 2 * av_clip(get_se_golomb(gb), -(1<<16), 1<<16);
852 ✗ int r6 = adjust(avg - bottommost, size);
853 ✗ int r9 = adjust(avg - rightmost, size);
854 ✗ int shift = adjust(size, size) == 8 ? 3 : 2;
855 uint8_t *block;
856
857 ✗ for (int x = 0; x < size; x++) {
858 ✗ int val = top[x];
859 ✗ arr1[x] = adjust(((bottommost - val) * (1 << shift)) + r6 * (x + 1), size);
860 }
861
862 ✗ for (int y = 0; y < size; y++) {
863 ✗ int val = left[y * frame->linesize[plane]];
864 ✗ arr2[y] = adjust(((rightmost - val) * (1 << shift)) + r9 * (y + 1), size);
865 }
866
867 ✗ block = frame->data[plane] + ay * frame->linesize[plane] + ax;
868 ✗ for (int y = 0; y < size; y++) {
869 ✗ for (int x = 0; x < size; x++) {
870 ✗ block[x] = (((top[x] + left[0] + ((arr1[x] * (y + 1) +
871 ✗ arr2[y] * (x + 1)) >> 2 * shift)) + 1) / 2) & 0xFF;
872 }
873 ✗ block += frame->linesize[plane];
874 ✗ left += frame->linesize[plane];
875 }
876 }
877 ✗ break;
878 ✗ case 3:
879 {
880 uint8_t fill;
881
882 ✗ if (ax == 0 && ay == 0) {
883 ✗ fill = 0x80;
884 ✗ } else if (ax >= 1 && ay >= 1) {
885 ✗ int left = block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1,
886 1, size, frame->linesize[plane]);
887 ✗ int top = block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax,
888 size, 1, frame->linesize[plane]);
889
890 ✗ fill = ((left + top) * 2 / (2 * size) + 1) / 2;
891 ✗ } else if (ax >= 1) {
892 ✗ fill = (block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1,
893 ✗ 1, size, frame->linesize[plane]) * 2 / size + 1) / 2;
894 ✗ } else if (ay >= 1) {
895 ✗ fill = (block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax,
896 ✗ size, 1, frame->linesize[plane]) * 2 / size + 1) / 2;
897 } else {
898 ✗ return -1;
899 }
900
901 ✗ block_fill_simple(frame->data[plane] + ay * frame->linesize[plane] + ax,
902 size, frame->linesize[plane], fill);
903 }
904 ✗ break;
905 ✗ case 4:
906 ✗ block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_4);
907 ✗ break;
908 ✗ case 5:
909 ✗ block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_5);
910 ✗ break;
911 ✗ case 6:
912 ✗ block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_6);
913 ✗ break;
914 ✗ case 7:
915 ✗ block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_7);
916 ✗ break;
917 ✗ case 8:
918 ✗ block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_8);
919 ✗ break;
920 }
921
922 ✗ if (add_coeffs)
923 ✗ ret = add_coefficients(avctx, frame, ax, ay, size, plane);
924
925 ✗ return ret;
926 }
927
928 ✗ static int get_prediction(AVCodecContext *avctx, int x, int y, int size)
929 {
930 ✗ MobiClipContext *s = avctx->priv_data;
931 ✗ GetBitContext *gb = &s->gb;
932 ✗ int index = (y & 0xC) | (x / 4 % 4);
933
934 ✗ uint8_t val = FFMIN(s->pre[index], index % 4 == 0 ? 9 : s->pre[index + 3]);
935 ✗ if (val == 9)
936 ✗ val = 3;
937
938 ✗ if (!get_bits1(gb)) {
939 ✗ int x = get_bits(gb, 3);
940 ✗ val = x + (x >= val ? 1 : 0);
941 }
942
943 ✗ s->pre[index + 4] = val;
944 ✗ if (size == 8)
945 ✗ s->pre[index + 5] = s->pre[index + 8] = s->pre[index + 9] = val;
946
947 ✗ return val;
948 }
949
950 ✗ static int process_block(AVCodecContext *avctx, AVFrame *frame,
951 int x, int y, int pmode, int has_coeffs, int plane)
952 {
953 ✗ MobiClipContext *s = avctx->priv_data;
954 ✗ GetBitContext *gb = &s->gb;
955 int tmp, ret;
956
957 ✗ if (!has_coeffs) {
958 ✗ if (pmode < 0)
959 ✗ pmode = get_prediction(avctx, x, y, 8);
960 ✗ return predict_intra(avctx, frame, x, y, pmode, 0, 8, plane);
961 }
962
963 ✗ tmp = get_ue_golomb_31(gb);
964 ✗ if ((unsigned)tmp > FF_ARRAY_ELEMS(block4x4_coefficients_tab))
965 ✗ return AVERROR_INVALIDDATA;
966
967 ✗ if (tmp == 0) {
968 ✗ if (pmode < 0)
969 ✗ pmode = get_prediction(avctx, x, y, 8);
970 ✗ ret = predict_intra(avctx, frame, x, y, pmode, 1, 8, plane);
971 } else {
972 ✗ int flags = block4x4_coefficients_tab[tmp - 1];
973
974 ✗ for (int by = y; by < y + 8; by += 4) {
975 ✗ for (int bx = x; bx < x + 8; bx += 4) {
976 ✗ int new_pmode = pmode;
977
978 ✗ if (new_pmode < 0)
979 ✗ new_pmode = get_prediction(avctx, bx, by, 4);
980 ✗ ret = predict_intra(avctx, frame, bx, by, new_pmode, flags & 1, 4, plane);
981 ✗ if (ret < 0)
982 ✗ return ret;
983 ✗ flags >>= 1;
984 }
985 }
986 }
987
988 ✗ return ret;
989 }
990
991 ✗ static int decode_macroblock(AVCodecContext *avctx, AVFrame *frame,
992 int x, int y, int predict)
993 {
994 ✗ MobiClipContext *s = avctx->priv_data;
995 ✗ GetBitContext *gb = &s->gb;
996 ✗ int flags, pmode_uv, idx = get_ue_golomb(gb);
997 ✗ int ret = 0;
998
999 ✗ if (idx < 0 || idx >= FF_ARRAY_ELEMS(block8x8_coefficients_tab))
1000 ✗ return AVERROR_INVALIDDATA;
1001
1002 ✗ flags = block8x8_coefficients_tab[idx];
1003
1004 ✗ if (predict) {
1005 ✗ ret = process_block(avctx, frame, x, y, -1, flags & 1, 0);
1006 ✗ if (ret < 0)
1007 ✗ return ret;
1008 ✗ flags >>= 1;
1009 ✗ ret = process_block(avctx, frame, x + 8, y, -1, flags & 1, 0);
1010 ✗ if (ret < 0)
1011 ✗ return ret;
1012 ✗ flags >>= 1;
1013 ✗ ret = process_block(avctx, frame, x, y + 8, -1, flags & 1, 0);
1014 ✗ if (ret < 0)
1015 ✗ return ret;
1016 ✗ flags >>= 1;
1017 ✗ ret = process_block(avctx, frame, x + 8, y + 8, -1, flags & 1, 0);
1018 ✗ if (ret < 0)
1019 ✗ return ret;
1020 ✗ flags >>= 1;
1021 } else {
1022 ✗ int pmode = get_bits(gb, 3);
1023
1024 ✗ if (pmode == 2) {
1025 ✗ ret = predict_intra(avctx, frame, x, y, pmode, 0, 16, 0);
1026 ✗ if (ret < 0)
1027 ✗ return ret;
1028 ✗ pmode = 9;
1029 }
1030
1031 ✗ ret = process_block(avctx, frame, x, y, pmode, flags & 1, 0);
1032 ✗ if (ret < 0)
1033 ✗ return ret;
1034 ✗ flags >>= 1;
1035 ✗ ret = process_block(avctx, frame, x + 8, y, pmode, flags & 1, 0);
1036 ✗ if (ret < 0)
1037 ✗ return ret;
1038 ✗ flags >>= 1;
1039 ✗ ret = process_block(avctx, frame, x, y + 8, pmode, flags & 1, 0);
1040 ✗ if (ret < 0)
1041 ✗ return ret;
1042 ✗ flags >>= 1;
1043 ✗ ret = process_block(avctx, frame, x + 8, y + 8, pmode, flags & 1, 0);
1044 ✗ if (ret < 0)
1045 ✗ return ret;
1046 ✗ flags >>= 1;
1047 }
1048
1049 ✗ pmode_uv = get_bits(gb, 3);
1050 ✗ if (pmode_uv == 2) {
1051 ✗ ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 1 + !s->moflex);
1052 ✗ if (ret < 0)
1053 ✗ return ret;
1054 ✗ ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 2 - !s->moflex);
1055 ✗ if (ret < 0)
1056 ✗ return ret;
1057 ✗ pmode_uv = 9;
1058 }
1059
1060 ✗ ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 1 + !s->moflex);
1061 ✗ if (ret < 0)
1062 ✗ return ret;
1063 ✗ flags >>= 1;
1064 ✗ ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 2 - !s->moflex);
1065 ✗ if (ret < 0)
1066 ✗ return ret;
1067
1068 ✗ return 0;
1069 }
1070
1071 ✗ static int get_index(int x)
1072 {
1073 ✗ return x == 16 ? 0 : x == 8 ? 1 : x == 4 ? 2 : x == 2 ? 3 : 0;
1074 }
1075
1076 ✗ static int predict_motion(AVCodecContext *avctx,
1077 int width, int height, int index,
1078 int offsetm, int offsetx, int offsety)
1079 {
1080 ✗ MobiClipContext *s = avctx->priv_data;
1081 ✗ MotionXY *motion = s->motion;
1082 ✗ GetBitContext *gb = &s->gb;
1083 ✗ int fheight = avctx->height;
1084 ✗ int fwidth = avctx->width;
1085
1086 ✗ if (index <= 5) {
1087 ✗ int sidx = -FFMAX(1, index) + s->current_pic;
1088 ✗ MotionXY mv = s->motion[0];
1089
1090 ✗ if (sidx < 0)
1091 ✗ sidx += 6;
1092
1093 ✗ if (index > 0) {
1094 ✗ mv.x = mv.x + (unsigned)get_se_golomb(gb);
1095 ✗ mv.y = mv.y + (unsigned)get_se_golomb(gb);
1096 }
1097 ✗ if (mv.x >= INT_MAX || mv.y >= INT_MAX)
1098 ✗ return AVERROR_INVALIDDATA;
1099
1100 ✗ motion[offsetm].x = mv.x;
1101 ✗ motion[offsetm].y = mv.y;
1102
1103 ✗ for (int i = 0; i < 3; i++) {
1104 int method, src_linesize, dst_linesize;
1105 uint8_t *src, *dst;
1106
1107 ✗ if (i == 1) {
1108 ✗ offsetx = offsetx >> 1;
1109 ✗ offsety = offsety >> 1;
1110 ✗ mv.x = mv.x >> 1;
1111 ✗ mv.y = mv.y >> 1;
1112 ✗ width = width >> 1;
1113 ✗ height = height >> 1;
1114 ✗ fwidth = fwidth >> 1;
1115 ✗ fheight = fheight >> 1;
1116 }
1117
1118 ✗ av_assert0(s->pic[sidx]);
1119 ✗ av_assert0(s->pic[s->current_pic]);
1120 ✗ av_assert0(s->pic[s->current_pic]->data[i]);
1121 ✗ if (!s->pic[sidx]->data[i])
1122 ✗ return AVERROR_INVALIDDATA;
1123
1124 ✗ method = (mv.x & 1) | ((mv.y & 1) << 1);
1125 ✗ src_linesize = s->pic[sidx]->linesize[i];
1126 ✗ dst_linesize = s->pic[s->current_pic]->linesize[i];
1127 ✗ dst = s->pic[s->current_pic]->data[i] + offsetx + offsety * dst_linesize;
1128
1129 ✗ if (offsetx + (mv.x >> 1) < 0 ||
1130 ✗ offsety + (mv.y >> 1) < 0 ||
1131 ✗ offsetx + width + (mv.x + 1 >> 1) > fwidth ||
1132 ✗ offsety + height + (mv.y + 1 >> 1) > fheight)
1133 ✗ return AVERROR_INVALIDDATA;
1134
1135 ✗ switch (method) {
1136 ✗ case 0:
1137 ✗ src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1138 ✗ (offsety + (mv.y >> 1)) * src_linesize;
1139 ✗ for (int y = 0; y < height; y++) {
1140 ✗ for (int x = 0; x < width; x++)
1141 ✗ dst[x] = src[x];
1142 ✗ dst += dst_linesize;
1143 ✗ src += src_linesize;
1144 }
1145 ✗ break;
1146 ✗ case 1:
1147 ✗ src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1148 ✗ (offsety + (mv.y >> 1)) * src_linesize;
1149 ✗ for (int y = 0; y < height; y++) {
1150 ✗ for (int x = 0; x < width; x++) {
1151 ✗ dst[x] = (uint8_t)((src[x] >> 1) + (src[x + 1] >> 1));
1152 }
1153
1154 ✗ dst += dst_linesize;
1155 ✗ src += src_linesize;
1156 }
1157 ✗ break;
1158 ✗ case 2:
1159 ✗ src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1160 ✗ (offsety + (mv.y >> 1)) * src_linesize;
1161 ✗ for (int y = 0; y < height; y++) {
1162 ✗ for (int x = 0; x < width; x++) {
1163 ✗ dst[x] = (uint8_t)((src[x] >> 1) + (src[x + src_linesize] >> 1));
1164 }
1165
1166 ✗ dst += dst_linesize;
1167 ✗ src += src_linesize;
1168 }
1169 ✗ break;
1170 ✗ case 3:
1171 ✗ src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1172 ✗ (offsety + (mv.y >> 1)) * src_linesize;
1173 ✗ for (int y = 0; y < height; y++) {
1174 ✗ for (int x = 0; x < width; x++) {
1175 ✗ dst[x] = (uint8_t)((((src[x] >> 1) + (src[x + 1] >> 1)) >> 1) +
1176 ✗ (((src[x + src_linesize] >> 1) + (src[x + 1 + src_linesize] >> 1)) >> 1));
1177 }
1178
1179 ✗ dst += dst_linesize;
1180 ✗ src += src_linesize;
1181 }
1182 ✗ break;
1183 }
1184 }
1185 } else {
1186 int tidx;
1187 ✗ int adjx = index == 8 ? 0 : width / 2;
1188 ✗ int adjy = index == 8 ? height / 2 : 0;
1189
1190 ✗ width = width - adjx;
1191 ✗ height = height - adjy;
1192 ✗ tidx = get_index(height) * 4 + get_index(width);
1193
1194 ✗ for (int i = 0; i < 2; i++) {
1195 int ret, idx2;
1196
1197 ✗ idx2 = get_vlc2(gb, mv_vlc[s->moflex][tidx], MOBI_MV_VLC_BITS, 1);
1198
1199 ✗ ret = predict_motion(avctx, width, height, idx2,
1200 ✗ offsetm, offsetx + i * adjx, offsety + i * adjy);
1201 ✗ if (ret < 0)
1202 ✗ return ret;
1203 }
1204 }
1205
1206 ✗ return 0;
1207 }
1208
1209 ✗ static int mobiclip_decode(AVCodecContext *avctx, AVFrame *rframe,
1210 int *got_frame, AVPacket *pkt)
1211 {
1212 ✗ MobiClipContext *s = avctx->priv_data;
1213 ✗ GetBitContext *gb = &s->gb;
1214 ✗ AVFrame *frame = s->pic[s->current_pic];
1215 int ret;
1216
1217 ✗ if (avctx->height/16 * (avctx->width/16) * 2 > 8LL*FFALIGN(pkt->size, 2))
1218 ✗ return AVERROR_INVALIDDATA;
1219
1220 ✗ av_fast_padded_malloc(&s->bitstream, &s->bitstream_size,
1221 ✗ pkt->size);
1222
1223 ✗ if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0)
1224 ✗ return ret;
1225
1226 ✗ s->bdsp.bswap16_buf((uint16_t *)s->bitstream,
1227 ✗ (uint16_t *)pkt->data,
1228 ✗ (pkt->size + 1) >> 1);
1229
1230 ✗ ret = init_get_bits8(gb, s->bitstream, FFALIGN(pkt->size, 2));
1231 ✗ if (ret < 0)
1232 ✗ return ret;
1233
1234 ✗ if (get_bits1(gb)) {
1235 ✗ frame->pict_type = AV_PICTURE_TYPE_I;
1236 ✗ frame->flags |= AV_FRAME_FLAG_KEY;
1237 ✗ s->moflex = get_bits1(gb);
1238 ✗ s->dct_tab_idx = get_bits1(gb);
1239
1240 ✗ ret = setup_qtables(avctx, get_bits(gb, 6));
1241 ✗ if (ret < 0)
1242 ✗ return ret;
1243
1244 ✗ for (int y = 0; y < avctx->height; y += 16) {
1245 ✗ for (int x = 0; x < avctx->width; x += 16) {
1246 ✗ ret = decode_macroblock(avctx, frame, x, y, get_bits1(gb));
1247 ✗ if (ret < 0)
1248 ✗ return ret;
1249 }
1250 }
1251 } else {
1252 ✗ MotionXY *motion = s->motion;
1253
1254 ✗ memset(motion, 0, s->motion_size);
1255
1256 ✗ frame->pict_type = AV_PICTURE_TYPE_P;
1257 ✗ frame->flags &= ~AV_FRAME_FLAG_KEY;
1258 ✗ s->dct_tab_idx = 0;
1259
1260 ✗ ret = setup_qtables(avctx, s->quantizer + (int64_t)get_se_golomb(gb));
1261 ✗ if (ret < 0)
1262 ✗ return ret;
1263
1264 ✗ for (int y = 0; y < avctx->height; y += 16) {
1265 ✗ for (int x = 0; x < avctx->width; x += 16) {
1266 int idx;
1267
1268 ✗ motion[0].x = mid_pred(motion[x / 16 + 1].x, motion[x / 16 + 2].x, motion[x / 16 + 3].x);
1269 ✗ motion[0].y = mid_pred(motion[x / 16 + 1].y, motion[x / 16 + 2].y, motion[x / 16 + 3].y);
1270 ✗ motion[x / 16 + 2].x = 0;
1271 ✗ motion[x / 16 + 2].y = 0;
1272
1273 ✗ idx = get_vlc2(gb, mv_vlc[s->moflex][0], MOBI_MV_VLC_BITS, 1);
1274
1275 ✗ if (idx == 6 || idx == 7) {
1276 ✗ ret = decode_macroblock(avctx, frame, x, y, idx == 7);
1277 ✗ if (ret < 0)
1278 ✗ return ret;
1279 } else {
1280 int flags, idx2;
1281 ✗ ret = predict_motion(avctx, 16, 16, idx, x / 16 + 2, x, y);
1282 ✗ if (ret < 0)
1283 ✗ return ret;
1284 ✗ idx2 = get_ue_golomb(gb);
1285 ✗ if (idx2 >= FF_ARRAY_ELEMS(pframe_block8x8_coefficients_tab))
1286 ✗ return AVERROR_INVALIDDATA;
1287 ✗ flags = pframe_block8x8_coefficients_tab[idx2];
1288
1289 ✗ for (int sy = y; sy < y + 16; sy += 8) {
1290 ✗ for (int sx = x; sx < x + 16; sx += 8) {
1291 ✗ if (flags & 1)
1292 ✗ add_pframe_coefficients(avctx, frame, sx, sy, 8, 0);
1293 ✗ flags >>= 1;
1294 }
1295 }
1296
1297 ✗ if (flags & 1)
1298 ✗ add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 1 + !s->moflex);
1299 ✗ flags >>= 1;
1300 ✗ if (flags & 1)
1301 ✗ add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 2 - !s->moflex);
1302 }
1303 }
1304 }
1305 }
1306
1307 ✗ if (!s->moflex)
1308 ✗ avctx->colorspace = AVCOL_SPC_YCGCO;
1309
1310 ✗ s->current_pic = (s->current_pic + 1) % 6;
1311 ✗ ret = av_frame_ref(rframe, frame);
1312 ✗ if (ret < 0)
1313 ✗ return ret;
1314 ✗ *got_frame = 1;
1315
1316 ✗ return 0;
1317 }
1318
1319 ✗ static av_cold void mobiclip_flush(AVCodecContext *avctx)
1320 {
1321 ✗ MobiClipContext *s = avctx->priv_data;
1322
1323 ✗ for (int i = 0; i < 6; i++)
1324 ✗ av_frame_unref(s->pic[i]);
1325 ✗ }
1326
1327 ✗ static av_cold int mobiclip_close(AVCodecContext *avctx)
1328 {
1329 ✗ MobiClipContext *s = avctx->priv_data;
1330
1331 ✗ av_freep(&s->bitstream);
1332 ✗ s->bitstream_size = 0;
1333 ✗ av_freep(&s->motion);
1334 ✗ s->motion_size = 0;
1335
1336 ✗ for (int i = 0; i < 6; i++) {
1337 ✗ av_frame_free(&s->pic[i]);
1338 }
1339
1340 ✗ return 0;
1341 }
1342
1343 const FFCodec ff_mobiclip_decoder = {
1344 .p.name = "mobiclip",
1345 CODEC_LONG_NAME("MobiClip Video"),
1346 .p.type = AVMEDIA_TYPE_VIDEO,
1347 .p.id = AV_CODEC_ID_MOBICLIP,
1348 .priv_data_size = sizeof(MobiClipContext),
1349 .init = mobiclip_init,
1350 FF_CODEC_DECODE_CB(mobiclip_decode),
1351 .flush = mobiclip_flush,
1352 .close = mobiclip_close,
1353 .p.capabilities = AV_CODEC_CAP_DR1,
1354 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
1355 };
1356