GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/mobiclip.c Lines: 0 667 0.0 %
Date: 2021-01-22 05:18:52 Branches: 0 353 0.0 %

Line Branch Exec Source
1
/*
2
 * MobiClip Video decoder
3
 * Copyright (c) 2017 Adib Surani
4
 * Copyright (c) 2020 Paul B Mahol
5
 *
6
 * This file is part of FFmpeg.
7
 *
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.
12
 *
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.
17
 *
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
21
 */
22
23
#include <inttypes.h>
24
25
#include "libavutil/avassert.h"
26
#include "libavutil/thread.h"
27
28
#include "avcodec.h"
29
#include "bytestream.h"
30
#include "bswapdsp.h"
31
#include "get_bits.h"
32
#include "golomb.h"
33
#include "internal.h"
34
35
#define MOBI_RL_VLC_BITS 12
36
#define MOBI_MV_VLC_BITS 6
37
38
static const uint8_t zigzag4x4_tab[] =
39
{
40
    0x00, 0x04, 0x01, 0x02, 0x05, 0x08, 0x0C, 0x09, 0x06, 0x03, 0x07, 0x0A,
41
    0x0D, 0x0E, 0x0B, 0x0F
42
};
43
44
static const uint8_t quant4x4_tab[][16] =
45
{
46
    { 10, 13, 13, 10, 16, 10, 13, 13, 13, 13, 16, 10, 16, 13, 13, 16 },
47
    { 11, 14, 14, 11, 18, 11, 14, 14, 14, 14, 18, 11, 18, 14, 14, 18 },
48
    { 13, 16, 16, 13, 20, 13, 16, 16, 16, 16, 20, 13, 20, 16, 16, 20 },
49
    { 14, 18, 18, 14, 23, 14, 18, 18, 18, 18, 23, 14, 23, 18, 18, 23 },
50
    { 16, 20, 20, 16, 25, 16, 20, 20, 20, 20, 25, 16, 25, 20, 20, 25 },
51
    { 18, 23, 23, 18, 29, 18, 23, 23, 23, 23, 29, 18, 29, 23, 23, 29 },
52
};
53
54
static const uint8_t quant8x8_tab[][64] =
55
{
56
    { 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,
57
      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,},
58
    { 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,
59
      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,},
60
    { 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,
61
      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,},
62
    { 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,
63
      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,},
64
    { 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,
65
      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,},
66
    { 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,
67
      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,},
68
};
69
70
static const uint8_t block4x4_coefficients_tab[] =
71
{
72
    15, 0, 2, 1, 4, 8, 12, 3, 11, 13, 14, 7, 10, 5, 9, 6,
73
};
74
75
static const uint8_t pframe_block4x4_coefficients_tab[] =
76
{
77
    0, 4, 1, 8, 2, 12, 3, 5, 10, 15, 7, 13, 14, 11, 9, 6,
78
};
79
80
static const uint8_t block8x8_coefficients_tab[] =
81
{
82
    0x00, 0x1F, 0x3F, 0x0F, 0x08, 0x04, 0x02, 0x01, 0x0B, 0x0E, 0x1B, 0x0D,
83
    0x03, 0x07, 0x0C, 0x17, 0x1D, 0x0A, 0x1E, 0x05, 0x10, 0x2F, 0x37, 0x3B,
84
    0x13, 0x3D, 0x3E, 0x09, 0x1C, 0x06, 0x15, 0x1A, 0x33, 0x11, 0x12, 0x14,
85
    0x18, 0x20, 0x3C, 0x35, 0x19, 0x16, 0x3A, 0x30, 0x31, 0x32, 0x27, 0x34,
86
    0x2B, 0x2D, 0x39, 0x38, 0x23, 0x36, 0x2E, 0x21, 0x25, 0x22, 0x24, 0x2C,
87
    0x2A, 0x28, 0x29, 0x26,
88
};
89
90
static const uint8_t pframe_block8x8_coefficients_tab[] =
91
{
92
    0x00, 0x0F, 0x04, 0x01, 0x08, 0x02, 0x0C, 0x03, 0x05, 0x0A, 0x0D, 0x07, 0x0E, 0x0B, 0x1F, 0x09,
93
    0x06, 0x10, 0x3F, 0x1E, 0x17, 0x1D, 0x1B, 0x1C, 0x13, 0x18, 0x1A, 0x12, 0x11, 0x14, 0x15, 0x20,
94
    0x2F, 0x16, 0x19, 0x37, 0x3D, 0x3E, 0x3B, 0x3C, 0x33, 0x35, 0x21, 0x24, 0x22, 0x28, 0x23, 0x2C,
95
    0x30, 0x27, 0x2D, 0x25, 0x3A, 0x2B, 0x2E, 0x2A, 0x31, 0x34, 0x38, 0x32, 0x29, 0x26, 0x39, 0x36
96
};
97
98
static const uint8_t run_residue[2][256] =
99
{
100
    {
101
       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,
102
        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,
103
        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,
104
        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,
105
        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,
106
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
107
        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,
108
        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,
109
    },
110
    {
111
       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,
112
        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,
113
        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,
114
        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,
115
        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,
116
        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,
117
        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,
118
        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,
119
    },
120
};
121
122
static const uint8_t bits0[] = {
123
     9, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
124
    10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12,
125
    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  7, 10, 10,  9,
126
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
127
     9,  9,  9,  9,  9,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
128
     8,  8,  8,  7,  7,  7,  7,  7,  7,  7,  7,  6,  6,  6,  6,
129
     6,  6,  6,  6,  6,  6,  5,  5,  5,  4,  2,  3,  4,  4,
130
};
131
132
static const uint16_t syms0[] = {
133
    0x0, 0x822, 0x803, 0xB, 0xA, 0xB81, 0xB61, 0xB41, 0xB21, 0x122,
134
    0x102, 0xE2, 0xC2, 0xA2, 0x63, 0x43, 0x24, 0xC, 0x25, 0x2E1, 0x301,
135
    0xBA1, 0xBC1, 0xBE1, 0xC01, 0x26, 0x44, 0x83, 0xA3, 0xC3, 0x142,
136
    0x321, 0x341, 0xC21, 0xC41, 0xC61, 0xC81, 0xCA1, 0xCC1, 0xCE1, 0xD01,
137
    0x0, 0x9, 0x8, 0xB01, 0xAE1, 0xAC1, 0xAA1, 0xA81, 0xA61, 0xA41, 0xA21,
138
    0x802, 0x2C1, 0x2A1, 0x281, 0x261, 0x241, 0x221, 0x201, 0x1E1, 0x82,
139
    0x62, 0x7, 0x6, 0xA01, 0x9E1, 0x9C1, 0x9A1, 0x981, 0x961, 0x941, 0x921,
140
    0x1C1, 0x1A1, 0x42, 0x23, 0x5, 0x901, 0x8E1, 0x8C1, 0x8A1, 0x181, 0x161,
141
    0x141, 0x4, 0x881, 0x861, 0x841, 0x821, 0x121, 0x101, 0xE1, 0xC1, 0x22,
142
    0x3, 0xA1, 0x81, 0x61, 0x801, 0x1, 0x21, 0x41, 0x2,
143
};
144
145
static const uint16_t syms1[] = {
146
    0x0, 0x807, 0x806, 0x16, 0x15, 0x842, 0x823, 0x805, 0x1A1, 0xA3, 0x102, 0x83,
147
    0x64, 0x44, 0x27, 0x14, 0x13, 0x17, 0x18, 0x28, 0x122, 0x862, 0x882, 0x9E1, 0xA01,
148
    0x19, 0x1A, 0x1B, 0x29, 0xC3, 0x2A, 0x45, 0xE3, 0x1C1, 0x808, 0x8A2, 0x8C2, 0xA21,
149
    0xA41, 0xA61, 0xA81, 0x0, 0x12, 0x11, 0x9C1, 0x9A1, 0x981, 0x961, 0x941, 0x822, 0x804,
150
    0x181, 0x161, 0xE2, 0xC2, 0xA2, 0x63, 0x43, 0x26, 0x25, 0x10, 0x82, 0xF, 0xE, 0xD, 0x901,
151
    0x8E1, 0x8C1, 0x803, 0x141, 0x121, 0x101, 0x921, 0x62, 0x24, 0xC, 0xB, 0xA, 0x881, 0x861,
152
    0xC1, 0x8A1, 0xE1, 0x42, 0x23, 0x9, 0x802, 0xA1, 0x841, 0x821, 0x81, 0x61, 0x8, 0x7, 0x22,
153
    0x6, 0x41, 0x5, 0x4, 0x801, 0x1, 0x2, 0x21, 0x3,
154
};
155
156
static const uint8_t mv_len[16] =
157
{
158
    10, 8, 8, 7, 8, 8, 8, 7, 8, 8, 8, 7, 7, 7, 7, 6,
159
};
160
161
static const uint8_t mv_bits[2][16][10] =
162
{
163
    {
164
        { 2, 3, 3, 5, 5, 4, 4, 5, 5, 2 },
165
        { 2, 3, 4, 4, 3, 4, 4, 2 },
166
        { 3, 4, 4, 2, 4, 4, 3, 2 },
167
        { 1, 3, 4, 5, 5, 3, 3 },
168
        { 2, 4, 4, 3, 3, 4, 4, 2 },
169
        { 2, 3, 4, 4, 4, 4, 3, 2 },
170
        { 2, 3, 4, 4, 4, 4, 3, 2 },
171
        { 2, 2, 3, 4, 5, 5, 2 },
172
        { 2, 3, 4, 4, 3, 4, 4, 2 },
173
        { 2, 4, 4, 3, 4, 4, 3, 2 },
174
        { 2, 3, 3, 5, 5, 4, 3, 2 },
175
        { 2, 3, 4, 4, 3, 3, 2 },
176
        { 1, 4, 4, 3, 3, 4, 4 },
177
        { 2, 3, 4, 4, 3, 3, 2 },
178
        { 2, 3, 4, 4, 3, 3, 2 },
179
        { 3, 3, 2, 2, 3, 3 },
180
    },
181
    {
182
        { 3, 4, 5, 5, 3, 5, 6, 6, 4, 1 },
183
        { 2, 3, 4, 5, 5, 2, 3, 3 },
184
        { 2, 4, 4, 3, 3, 4, 4, 2 },
185
        { 1, 4, 4, 3, 4, 4, 3 },
186
        { 3, 3, 2, 4, 5, 5, 3, 2 },
187
        { 3, 4, 4, 3, 3, 3, 3, 2 },
188
        { 1, 3, 3, 4, 4, 4, 5, 5 },
189
        { 1, 4, 4, 3, 3, 4, 4 },
190
        { 2, 4, 4, 3, 3, 4, 4, 2 },
191
        { 1, 3, 3, 4, 4, 4, 5, 5 },
192
        { 2, 3, 4, 4, 4, 4, 3, 2 },
193
        { 2, 3, 3, 4, 4, 3, 2 },
194
        { 1, 4, 4, 3, 3, 4, 4 },
195
        { 1, 4, 4, 3, 3, 4, 4 },
196
        { 2, 3, 3, 4, 4, 3, 2 },
197
        { 2, 3, 3, 3, 3, 2 },
198
    }
199
};
200
201
static const uint8_t mv_syms[2][16][10] =
202
{
203
    {
204
        { 1, 8, 9, 4, 3, 2, 7, 5, 6, 0 },
205
        { 0, 9, 5, 4, 2, 3, 8, 1 },
206
        { 3, 9, 5, 0, 4, 8, 2, 1 },
207
        { 1, 3, 4, 8, 5, 2, 0 },
208
        { 0, 5, 4, 8, 2, 3, 9, 1 },
209
        { 0, 3, 5, 9, 4, 8, 2, 1 },
210
        { 0, 3, 9, 5, 8, 4, 2, 1 },
211
        { 0, 2, 3, 4, 8, 5, 1 },
212
        { 0, 3, 8, 4, 2, 5, 9, 1 },
213
        { 2, 8, 9, 3, 5, 4, 0, 1 },
214
        { 0, 4, 3, 8, 9, 5, 2, 1 },
215
        { 0, 4, 8, 5, 3, 2, 1 },
216
        { 1, 9, 4, 2, 0, 5, 3 },
217
        { 2, 4, 9, 5, 3, 0, 1 },
218
        { 0, 4, 9, 5, 3, 2, 1 },
219
        { 5, 4, 1, 0, 3, 2 },
220
    },
221
    {
222
        { 8, 2, 3, 6, 1, 7, 5, 4, 9, 0 },
223
        { 9, 2, 3, 5, 4, 1, 8, 0 },
224
        { 0, 5, 4, 2, 9, 3, 8, 1 },
225
        { 1, 5, 4, 2, 8, 3, 0 },
226
        { 2, 9, 8, 3, 5, 4, 0, 1 },
227
        { 3, 5, 4, 2, 9, 8, 0, 1 },
228
        { 1, 2, 0, 9, 8, 3, 5, 4 },
229
        { 1, 8, 5, 2, 0, 4, 3 },
230
        { 0, 5, 4, 2, 8, 3, 9, 1 },
231
        { 1, 2, 0, 9, 8, 3, 5, 4 },
232
        { 0, 3, 9, 8, 5, 4, 2, 1 },
233
        { 0, 4, 3, 8, 5, 2, 1 },
234
        { 1, 5, 4, 2, 0, 9, 3 },
235
        { 1, 9, 5, 2, 0, 4, 3 },
236
        { 0, 5, 3, 9, 4, 2, 1 },
237
        { 0, 4, 5, 3, 2, 1 },
238
    }
239
};
240
241
typedef struct BlockXY {
242
    int w, h;
243
    int ax, ay;
244
    int x, y;
245
    int size;
246
    uint8_t *block;
247
    int linesize;
248
} BlockXY;
249
250
typedef struct MotionXY {
251
    int x, y;
252
} MotionXY;
253
254
typedef struct MobiClipContext {
255
    AVFrame *pic[6];
256
257
    int current_pic;
258
    int moflex;
259
    int dct_tab_idx;
260
    int quantizer;
261
262
    GetBitContext gb;
263
264
    uint8_t *bitstream;
265
    int bitstream_size;
266
267
    int     qtab[2][64];
268
    uint8_t pre[32];
269
    MotionXY *motion;
270
    int     motion_size;
271
272
    BswapDSPContext bdsp;
273
} MobiClipContext;
274
275
static VLC rl_vlc[2];
276
static VLC mv_vlc[2][16];
277
278
static av_cold void mobiclip_init_static(void)
279
{
280
    INIT_VLC_STATIC_FROM_LENGTHS(&rl_vlc[0], MOBI_RL_VLC_BITS, 104,
281
                                 bits0, sizeof(*bits0),
282
                                 syms0, sizeof(*syms0), sizeof(*syms0),
283
                                 0, 0, 1 << MOBI_RL_VLC_BITS);
284
    INIT_VLC_STATIC_FROM_LENGTHS(&rl_vlc[1], MOBI_RL_VLC_BITS, 104,
285
                                 bits0, sizeof(*bits0),
286
                                 syms1, sizeof(*syms1), sizeof(*syms1),
287
                                 0, 0, 1 << MOBI_RL_VLC_BITS);
288
    for (int i = 0; i < 2; i++) {
289
        static VLC_TYPE vlc_buf[2 * 16 << MOBI_MV_VLC_BITS][2];
290
        for (int j = 0; j < 16; j++) {
291
            mv_vlc[i][j].table           = &vlc_buf[(16 * i + j) << MOBI_MV_VLC_BITS];
292
            mv_vlc[i][j].table_allocated = 1 << MOBI_MV_VLC_BITS;
293
            ff_init_vlc_from_lengths(&mv_vlc[i][j], MOBI_MV_VLC_BITS, mv_len[j],
294
                                     mv_bits[i][j], sizeof(*mv_bits[i][j]),
295
                                     mv_syms[i][j], sizeof(*mv_syms[i][j]), sizeof(*mv_syms[i][j]),
296
                                     0, INIT_VLC_USE_NEW_STATIC, NULL);
297
        }
298
    }
299
}
300
301
static av_cold int mobiclip_init(AVCodecContext *avctx)
302
{
303
    static AVOnce init_static_once = AV_ONCE_INIT;
304
    MobiClipContext *s = avctx->priv_data;
305
306
    if (avctx->width & 15 || avctx->height & 15) {
307
        av_log(avctx, AV_LOG_ERROR, "width/height not multiple of 16\n");
308
        return AVERROR_INVALIDDATA;
309
    }
310
311
    ff_bswapdsp_init(&s->bdsp);
312
313
    avctx->pix_fmt = AV_PIX_FMT_YUV420P;
314
315
    s->motion = av_calloc(avctx->width / 16 + 3, sizeof(MotionXY));
316
    if (!s->motion)
317
        return AVERROR(ENOMEM);
318
    s->motion_size = (avctx->width / 16 + 3) * sizeof(MotionXY);
319
320
    for (int i = 0; i < 6; i++) {
321
        s->pic[i] = av_frame_alloc();
322
        if (!s->pic[i])
323
            return AVERROR(ENOMEM);
324
    }
325
326
    ff_thread_once(&init_static_once, mobiclip_init_static);
327
328
    return 0;
329
}
330
331
static int setup_qtables(AVCodecContext *avctx, int quantizer)
332
{
333
    MobiClipContext *s = avctx->priv_data;
334
    int qx, qy;
335
336
    if (quantizer < 12 || quantizer > 161)
337
        return AVERROR_INVALIDDATA;
338
339
    s->quantizer = quantizer;
340
341
    qx = quantizer % 6;
342
    qy = quantizer / 6;
343
344
    for (int i = 0; i < 16; i++)
345
        s->qtab[0][i] = quant4x4_tab[qx][i] << qy;
346
347
    for (int i = 0; i < 64; i++)
348
        s->qtab[1][i] = quant8x8_tab[qx][i] << (qy - 2);
349
350
    for (int i = 0; i < 20; i++)
351
        s->pre[i] = 9;
352
353
    return 0;
354
}
355
356
static void inverse4(unsigned *rs)
357
{
358
    unsigned a = rs[0] + rs[2];
359
    unsigned b = rs[0] - rs[2];
360
    unsigned c = rs[1] + ((int)rs[3] >> 1);
361
    unsigned d = ((int)rs[1] >> 1) - rs[3];
362
363
    rs[0] = a + c;
364
    rs[1] = b + d;
365
    rs[2] = b - d;
366
    rs[3] = a - c;
367
}
368
369
static void idct(int *arr, int size)
370
{
371
    int e, f, g, h;
372
    unsigned x3, x2, x1, x0;
373
    int tmp[4];
374
375
    if (size == 4) {
376
        inverse4(arr);
377
        return;
378
    }
379
380
    tmp[0] = arr[0];
381
    tmp[1] = arr[2];
382
    tmp[2] = arr[4];
383
    tmp[3] = arr[6];
384
385
    inverse4(tmp);
386
387
    e = (unsigned)arr[7] + arr[1] - arr[3] - (arr[3] >> 1);
388
    f = (unsigned)arr[7] - arr[1] + arr[5] + (arr[5] >> 1);
389
    g = (unsigned)arr[5] - arr[3] - arr[7] - (arr[7] >> 1);
390
    h = (unsigned)arr[5] + arr[3] + arr[1] + (arr[1] >> 1);
391
    x3 = (unsigned)g + (h >> 2);
392
    x2 = (unsigned)e + (f >> 2);
393
    x1 = (e >> 2) - (unsigned)f;
394
    x0 = (unsigned)h - (g >> 2);
395
396
    arr[0] = tmp[0] + x0;
397
    arr[1] = tmp[1] + x1;
398
    arr[2] = tmp[2] + x2;
399
    arr[3] = tmp[3] + x3;
400
    arr[4] = tmp[3] - x3;
401
    arr[5] = tmp[2] - x2;
402
    arr[6] = tmp[1] - x1;
403
    arr[7] = tmp[0] - x0;
404
}
405
406
static void read_run_encoding(AVCodecContext *avctx,
407
                              int *last, int *run, int *level)
408
{
409
    MobiClipContext *s = avctx->priv_data;
410
    GetBitContext *gb = &s->gb;
411
    int n = get_vlc2(gb, rl_vlc[s->dct_tab_idx].table,
412
                     MOBI_RL_VLC_BITS, 1);
413
414
    *last = (n >> 11) == 1;
415
    *run  = (n >> 5) & 0x3F;
416
    *level = n & 0x1F;
417
}
418
419
static int add_coefficients(AVCodecContext *avctx, AVFrame *frame,
420
                            int bx, int by, int size, int plane)
421
{
422
    MobiClipContext *s = avctx->priv_data;
423
    GetBitContext *gb = &s->gb;
424
    int mat[64] = { 0 };
425
    const uint8_t *ztab = size == 8 ? ff_zigzag_direct : zigzag4x4_tab;
426
    const int *qtab = s->qtab[size == 8];
427
    uint8_t *dst = frame->data[plane] + by * frame->linesize[plane] + bx;
428
429
    for (int pos = 0; get_bits_left(gb) > 0; pos++) {
430
        int qval, last, run, level;
431
432
        read_run_encoding(avctx, &last, &run, &level);
433
434
        if (level) {
435
            if (get_bits1(gb))
436
                level = -level;
437
        } else if (!get_bits1(gb)) {
438
            read_run_encoding(avctx, &last, &run, &level);
439
            level += run_residue[s->dct_tab_idx][(last ? 64 : 0) + run];
440
            if (get_bits1(gb))
441
                level = -level;
442
        } else if (!get_bits1(gb)) {
443
            read_run_encoding(avctx, &last, &run, &level);
444
            run += run_residue[s->dct_tab_idx][128 + (last ? 64 : 0) + level];
445
            if (get_bits1(gb))
446
                level = -level;
447
        } else {
448
            last  = get_bits1(gb);
449
            run   = get_bits(gb, 6);
450
            level = get_sbits(gb, 12);
451
        }
452
453
        pos += run;
454
        if (pos >= size * size)
455
            return AVERROR_INVALIDDATA;
456
        qval = qtab[pos];
457
        mat[ztab[pos]] = qval *(unsigned)level;
458
459
        if (last)
460
            break;
461
    }
462
463
    mat[0] += 32;
464
    for (int y = 0; y < size; y++)
465
        idct(&mat[y * size], size);
466
467
    for (int y = 0; y < size; y++) {
468
        for (int x = y + 1; x < size; x++) {
469
            int a = mat[x * size + y];
470
            int b = mat[y * size + x];
471
472
            mat[y * size + x] = a;
473
            mat[x * size + y] = b;
474
        }
475
476
        idct(&mat[y * size], size);
477
        for (int x = 0; x < size; x++)
478
            dst[x] = av_clip_uint8(dst[x] + (mat[y * size + x] >> 6));
479
        dst += frame->linesize[plane];
480
    }
481
482
    return 0;
483
}
484
485
static int add_pframe_coefficients(AVCodecContext *avctx, AVFrame *frame,
486
                                   int bx, int by, int size, int plane)
487
{
488
    MobiClipContext *s = avctx->priv_data;
489
    GetBitContext *gb = &s->gb;
490
    int ret, idx = get_ue_golomb_31(gb);
491
492
    if (idx == 0) {
493
        ret = add_coefficients(avctx, frame, bx, by, size, plane);
494
    } else if ((unsigned)idx < FF_ARRAY_ELEMS(pframe_block4x4_coefficients_tab)) {
495
        int flags = pframe_block4x4_coefficients_tab[idx];
496
497
        for (int y = by; y < by + 8; y += 4) {
498
            for (int x = bx; x < bx + 8; x += 4) {
499
                if (flags & 1) {
500
                    ret = add_coefficients(avctx, frame, x, y, 4, plane);
501
                    if (ret < 0)
502
                        return ret;
503
                }
504
                flags >>= 1;
505
            }
506
        }
507
    } else {
508
        ret = AVERROR_INVALIDDATA;
509
    }
510
511
    return ret;
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 * get_se_golomb(gb);
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 + get_se_golomb(gb);
1095
            mv.y = mv.y + 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].table,
1198
                            MOBI_MV_VLC_BITS, 1);
1199
1200
            ret = predict_motion(avctx, width, height, idx2,
1201
                                 offsetm, offsetx + i * adjx, offsety + i * adjy);
1202
            if (ret < 0)
1203
                return ret;
1204
        }
1205
    }
1206
1207
    return 0;
1208
}
1209
1210
static int mobiclip_decode(AVCodecContext *avctx, void *data,
1211
                            int *got_frame, AVPacket *pkt)
1212
{
1213
    MobiClipContext *s = avctx->priv_data;
1214
    GetBitContext *gb = &s->gb;
1215
    AVFrame *frame = s->pic[s->current_pic];
1216
    int ret;
1217
1218
    av_fast_padded_malloc(&s->bitstream, &s->bitstream_size,
1219
                          pkt->size);
1220
1221
    if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0)
1222
        return ret;
1223
1224
    s->bdsp.bswap16_buf((uint16_t *)s->bitstream,
1225
                        (uint16_t *)pkt->data,
1226
                        (pkt->size + 1) >> 1);
1227
1228
    ret = init_get_bits8(gb, s->bitstream, FFALIGN(pkt->size, 2));
1229
    if (ret < 0)
1230
        return ret;
1231
1232
    if (get_bits1(gb)) {
1233
        frame->pict_type = AV_PICTURE_TYPE_I;
1234
        frame->key_frame = 1;
1235
        s->moflex = get_bits1(gb);
1236
        s->dct_tab_idx = get_bits1(gb);
1237
1238
        ret = setup_qtables(avctx, get_bits(gb, 6));
1239
        if (ret < 0)
1240
            return ret;
1241
1242
        for (int y = 0; y < avctx->height; y += 16) {
1243
            for (int x = 0; x < avctx->width; x += 16) {
1244
                ret = decode_macroblock(avctx, frame, x, y, get_bits1(gb));
1245
                if (ret < 0)
1246
                    return ret;
1247
            }
1248
        }
1249
    } else {
1250
        MotionXY *motion = s->motion;
1251
1252
        memset(motion, 0, s->motion_size);
1253
1254
        frame->pict_type = AV_PICTURE_TYPE_P;
1255
        frame->key_frame = 0;
1256
        s->dct_tab_idx = 0;
1257
1258
        ret = setup_qtables(avctx, s->quantizer + get_se_golomb(gb));
1259
        if (ret < 0)
1260
            return ret;
1261
1262
        for (int y = 0; y < avctx->height; y += 16) {
1263
            for (int x = 0; x < avctx->width; x += 16) {
1264
                int idx;
1265
1266
                motion[0].x = mid_pred(motion[x / 16 + 1].x, motion[x / 16 + 2].x, motion[x / 16 + 3].x);
1267
                motion[0].y = mid_pred(motion[x / 16 + 1].y, motion[x / 16 + 2].y, motion[x / 16 + 3].y);
1268
                motion[x / 16 + 2].x = 0;
1269
                motion[x / 16 + 2].y = 0;
1270
1271
                idx = get_vlc2(gb, mv_vlc[s->moflex][0].table,
1272
                                   MOBI_MV_VLC_BITS, 1);
1273
1274
                if (idx == 6 || idx == 7) {
1275
                    ret = decode_macroblock(avctx, frame, x, y, idx == 7);
1276
                    if (ret < 0)
1277
                        return ret;
1278
                } else {
1279
                    int flags, idx2;
1280
                    ret = predict_motion(avctx, 16, 16, idx, x / 16 + 2, x, y);
1281
                    if (ret < 0)
1282
                        return ret;
1283
                    idx2 = get_ue_golomb(gb);
1284
                    if (idx2 >= FF_ARRAY_ELEMS(pframe_block8x8_coefficients_tab))
1285
                        return AVERROR_INVALIDDATA;
1286
                    flags = pframe_block8x8_coefficients_tab[idx2];
1287
1288
                    for (int sy = y; sy < y + 16; sy += 8) {
1289
                        for (int sx = x; sx < x + 16; sx += 8) {
1290
                            if (flags & 1)
1291
                                add_pframe_coefficients(avctx, frame, sx, sy, 8, 0);
1292
                            flags >>= 1;
1293
                        }
1294
                    }
1295
1296
                    if (flags & 1)
1297
                        add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 1 + !s->moflex);
1298
                    flags >>= 1;
1299
                    if (flags & 1)
1300
                        add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 2 - !s->moflex);
1301
                }
1302
            }
1303
        }
1304
    }
1305
1306
    if (!s->moflex)
1307
        avctx->colorspace = AVCOL_SPC_YCGCO;
1308
1309
    s->current_pic = (s->current_pic + 1) % 6;
1310
    ret = av_frame_ref(data, frame);
1311
    if (ret < 0)
1312
        return ret;
1313
    *got_frame = 1;
1314
1315
    return 0;
1316
}
1317
1318
static void mobiclip_flush(AVCodecContext *avctx)
1319
{
1320
    MobiClipContext *s = avctx->priv_data;
1321
1322
    for (int i = 0; i < 6; i++)
1323
        av_frame_unref(s->pic[i]);
1324
}
1325
1326
static av_cold int mobiclip_close(AVCodecContext *avctx)
1327
{
1328
    MobiClipContext *s = avctx->priv_data;
1329
1330
    av_freep(&s->bitstream);
1331
    s->bitstream_size = 0;
1332
    av_freep(&s->motion);
1333
    s->motion_size = 0;
1334
1335
    for (int i = 0; i < 6; i++) {
1336
        av_frame_free(&s->pic[i]);
1337
    }
1338
1339
    return 0;
1340
}
1341
1342
AVCodec ff_mobiclip_decoder = {
1343
    .name           = "mobiclip",
1344
    .long_name      = NULL_IF_CONFIG_SMALL("MobiClip Video"),
1345
    .type           = AVMEDIA_TYPE_VIDEO,
1346
    .id             = AV_CODEC_ID_MOBICLIP,
1347
    .priv_data_size = sizeof(MobiClipContext),
1348
    .init           = mobiclip_init,
1349
    .decode         = mobiclip_decode,
1350
    .flush          = mobiclip_flush,
1351
    .close          = mobiclip_close,
1352
    .capabilities   = AV_CODEC_CAP_DR1,
1353
    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
1354
};