FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/mobiclip.c
Date: 2025-10-10 03:51:19
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