FFmpeg
mobiclip.c
Go to the documentation of this file.
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/avassert.h"
27 #include "libavutil/thread.h"
28 
29 #include "avcodec.h"
30 #include "bswapdsp.h"
31 #include "codec_internal.h"
32 #include "decode.h"
33 #include "get_bits.h"
34 #include "golomb.h"
35 #include "mathops.h"
36 
37 #define MOBI_RL_VLC_BITS 12
38 #define MOBI_MV_VLC_BITS 6
39 
40 static const uint8_t zigzag4x4_tab[] =
41 {
42  0x00, 0x04, 0x01, 0x02, 0x05, 0x08, 0x0C, 0x09, 0x06, 0x03, 0x07, 0x0A,
43  0x0D, 0x0E, 0x0B, 0x0F
44 };
45 
46 static const uint8_t quant4x4_tab[][16] =
47 {
48  { 10, 13, 13, 10, 16, 10, 13, 13, 13, 13, 16, 10, 16, 13, 13, 16 },
49  { 11, 14, 14, 11, 18, 11, 14, 14, 14, 14, 18, 11, 18, 14, 14, 18 },
50  { 13, 16, 16, 13, 20, 13, 16, 16, 16, 16, 20, 13, 20, 16, 16, 20 },
51  { 14, 18, 18, 14, 23, 14, 18, 18, 18, 18, 23, 14, 23, 18, 18, 23 },
52  { 16, 20, 20, 16, 25, 16, 20, 20, 20, 20, 25, 16, 25, 20, 20, 25 },
53  { 18, 23, 23, 18, 29, 18, 23, 23, 23, 23, 29, 18, 29, 23, 23, 29 },
54 };
55 
56 static const uint8_t quant8x8_tab[][64] =
57 {
58  { 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,
59  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,},
60  { 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,
61  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,},
62  { 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,
63  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,},
64  { 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,
65  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,},
66  { 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,
67  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,},
68  { 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,
69  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,},
70 };
71 
72 static const uint8_t block4x4_coefficients_tab[] =
73 {
74  15, 0, 2, 1, 4, 8, 12, 3, 11, 13, 14, 7, 10, 5, 9, 6,
75 };
76 
77 static const uint8_t pframe_block4x4_coefficients_tab[] =
78 {
79  0, 4, 1, 8, 2, 12, 3, 5, 10, 15, 7, 13, 14, 11, 9, 6,
80 };
81 
82 static const uint8_t block8x8_coefficients_tab[] =
83 {
84  0x00, 0x1F, 0x3F, 0x0F, 0x08, 0x04, 0x02, 0x01, 0x0B, 0x0E, 0x1B, 0x0D,
85  0x03, 0x07, 0x0C, 0x17, 0x1D, 0x0A, 0x1E, 0x05, 0x10, 0x2F, 0x37, 0x3B,
86  0x13, 0x3D, 0x3E, 0x09, 0x1C, 0x06, 0x15, 0x1A, 0x33, 0x11, 0x12, 0x14,
87  0x18, 0x20, 0x3C, 0x35, 0x19, 0x16, 0x3A, 0x30, 0x31, 0x32, 0x27, 0x34,
88  0x2B, 0x2D, 0x39, 0x38, 0x23, 0x36, 0x2E, 0x21, 0x25, 0x22, 0x24, 0x2C,
89  0x2A, 0x28, 0x29, 0x26,
90 };
91 
92 static const uint8_t pframe_block8x8_coefficients_tab[] =
93 {
94  0x00, 0x0F, 0x04, 0x01, 0x08, 0x02, 0x0C, 0x03, 0x05, 0x0A, 0x0D, 0x07, 0x0E, 0x0B, 0x1F, 0x09,
95  0x06, 0x10, 0x3F, 0x1E, 0x17, 0x1D, 0x1B, 0x1C, 0x13, 0x18, 0x1A, 0x12, 0x11, 0x14, 0x15, 0x20,
96  0x2F, 0x16, 0x19, 0x37, 0x3D, 0x3E, 0x3B, 0x3C, 0x33, 0x35, 0x21, 0x24, 0x22, 0x28, 0x23, 0x2C,
97  0x30, 0x27, 0x2D, 0x25, 0x3A, 0x2B, 0x2E, 0x2A, 0x31, 0x34, 0x38, 0x32, 0x29, 0x26, 0x39, 0x36
98 };
99 
100 static const uint8_t run_residue[2][256] =
101 {
102  {
103  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,
104  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,
105  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,
106  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,
107  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,
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  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,
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  },
112  {
113  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,
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  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,
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  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,
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  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,
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  },
122 };
123 
124 static const uint8_t bits0[] = {
125  9, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
126  10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12,
127  12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 10, 10, 9,
128  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
129  9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
130  8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6,
131  6, 6, 6, 6, 6, 6, 5, 5, 5, 4, 2, 3, 4, 4,
132 };
133 
134 static const uint16_t syms0[] = {
135  0x0, 0x822, 0x803, 0xB, 0xA, 0xB81, 0xB61, 0xB41, 0xB21, 0x122,
136  0x102, 0xE2, 0xC2, 0xA2, 0x63, 0x43, 0x24, 0xC, 0x25, 0x2E1, 0x301,
137  0xBA1, 0xBC1, 0xBE1, 0xC01, 0x26, 0x44, 0x83, 0xA3, 0xC3, 0x142,
138  0x321, 0x341, 0xC21, 0xC41, 0xC61, 0xC81, 0xCA1, 0xCC1, 0xCE1, 0xD01,
139  0x0, 0x9, 0x8, 0xB01, 0xAE1, 0xAC1, 0xAA1, 0xA81, 0xA61, 0xA41, 0xA21,
140  0x802, 0x2C1, 0x2A1, 0x281, 0x261, 0x241, 0x221, 0x201, 0x1E1, 0x82,
141  0x62, 0x7, 0x6, 0xA01, 0x9E1, 0x9C1, 0x9A1, 0x981, 0x961, 0x941, 0x921,
142  0x1C1, 0x1A1, 0x42, 0x23, 0x5, 0x901, 0x8E1, 0x8C1, 0x8A1, 0x181, 0x161,
143  0x141, 0x4, 0x881, 0x861, 0x841, 0x821, 0x121, 0x101, 0xE1, 0xC1, 0x22,
144  0x3, 0xA1, 0x81, 0x61, 0x801, 0x1, 0x21, 0x41, 0x2,
145 };
146 
147 static const uint16_t syms1[] = {
148  0x0, 0x807, 0x806, 0x16, 0x15, 0x842, 0x823, 0x805, 0x1A1, 0xA3, 0x102, 0x83,
149  0x64, 0x44, 0x27, 0x14, 0x13, 0x17, 0x18, 0x28, 0x122, 0x862, 0x882, 0x9E1, 0xA01,
150  0x19, 0x1A, 0x1B, 0x29, 0xC3, 0x2A, 0x45, 0xE3, 0x1C1, 0x808, 0x8A2, 0x8C2, 0xA21,
151  0xA41, 0xA61, 0xA81, 0x0, 0x12, 0x11, 0x9C1, 0x9A1, 0x981, 0x961, 0x941, 0x822, 0x804,
152  0x181, 0x161, 0xE2, 0xC2, 0xA2, 0x63, 0x43, 0x26, 0x25, 0x10, 0x82, 0xF, 0xE, 0xD, 0x901,
153  0x8E1, 0x8C1, 0x803, 0x141, 0x121, 0x101, 0x921, 0x62, 0x24, 0xC, 0xB, 0xA, 0x881, 0x861,
154  0xC1, 0x8A1, 0xE1, 0x42, 0x23, 0x9, 0x802, 0xA1, 0x841, 0x821, 0x81, 0x61, 0x8, 0x7, 0x22,
155  0x6, 0x41, 0x5, 0x4, 0x801, 0x1, 0x2, 0x21, 0x3,
156 };
157 
158 static const uint8_t mv_len[16] =
159 {
160  10, 8, 8, 7, 8, 8, 8, 7, 8, 8, 8, 7, 7, 7, 7, 6,
161 };
162 
163 static const uint8_t mv_bits[2][16][10] =
164 {
165  {
166  { 2, 3, 3, 5, 5, 4, 4, 5, 5, 2 },
167  { 2, 3, 4, 4, 3, 4, 4, 2 },
168  { 3, 4, 4, 2, 4, 4, 3, 2 },
169  { 1, 3, 4, 5, 5, 3, 3 },
170  { 2, 4, 4, 3, 3, 4, 4, 2 },
171  { 2, 3, 4, 4, 4, 4, 3, 2 },
172  { 2, 3, 4, 4, 4, 4, 3, 2 },
173  { 2, 2, 3, 4, 5, 5, 2 },
174  { 2, 3, 4, 4, 3, 4, 4, 2 },
175  { 2, 4, 4, 3, 4, 4, 3, 2 },
176  { 2, 3, 3, 5, 5, 4, 3, 2 },
177  { 2, 3, 4, 4, 3, 3, 2 },
178  { 1, 4, 4, 3, 3, 4, 4 },
179  { 2, 3, 4, 4, 3, 3, 2 },
180  { 2, 3, 4, 4, 3, 3, 2 },
181  { 3, 3, 2, 2, 3, 3 },
182  },
183  {
184  { 3, 4, 5, 5, 3, 5, 6, 6, 4, 1 },
185  { 2, 3, 4, 5, 5, 2, 3, 3 },
186  { 2, 4, 4, 3, 3, 4, 4, 2 },
187  { 1, 4, 4, 3, 4, 4, 3 },
188  { 3, 3, 2, 4, 5, 5, 3, 2 },
189  { 3, 4, 4, 3, 3, 3, 3, 2 },
190  { 1, 3, 3, 4, 4, 4, 5, 5 },
191  { 1, 4, 4, 3, 3, 4, 4 },
192  { 2, 4, 4, 3, 3, 4, 4, 2 },
193  { 1, 3, 3, 4, 4, 4, 5, 5 },
194  { 2, 3, 4, 4, 4, 4, 3, 2 },
195  { 2, 3, 3, 4, 4, 3, 2 },
196  { 1, 4, 4, 3, 3, 4, 4 },
197  { 1, 4, 4, 3, 3, 4, 4 },
198  { 2, 3, 3, 4, 4, 3, 2 },
199  { 2, 3, 3, 3, 3, 2 },
200  }
201 };
202 
203 static const uint8_t mv_syms[2][16][10] =
204 {
205  {
206  { 1, 8, 9, 4, 3, 2, 7, 5, 6, 0 },
207  { 0, 9, 5, 4, 2, 3, 8, 1 },
208  { 3, 9, 5, 0, 4, 8, 2, 1 },
209  { 1, 3, 4, 8, 5, 2, 0 },
210  { 0, 5, 4, 8, 2, 3, 9, 1 },
211  { 0, 3, 5, 9, 4, 8, 2, 1 },
212  { 0, 3, 9, 5, 8, 4, 2, 1 },
213  { 0, 2, 3, 4, 8, 5, 1 },
214  { 0, 3, 8, 4, 2, 5, 9, 1 },
215  { 2, 8, 9, 3, 5, 4, 0, 1 },
216  { 0, 4, 3, 8, 9, 5, 2, 1 },
217  { 0, 4, 8, 5, 3, 2, 1 },
218  { 1, 9, 4, 2, 0, 5, 3 },
219  { 2, 4, 9, 5, 3, 0, 1 },
220  { 0, 4, 9, 5, 3, 2, 1 },
221  { 5, 4, 1, 0, 3, 2 },
222  },
223  {
224  { 8, 2, 3, 6, 1, 7, 5, 4, 9, 0 },
225  { 9, 2, 3, 5, 4, 1, 8, 0 },
226  { 0, 5, 4, 2, 9, 3, 8, 1 },
227  { 1, 5, 4, 2, 8, 3, 0 },
228  { 2, 9, 8, 3, 5, 4, 0, 1 },
229  { 3, 5, 4, 2, 9, 8, 0, 1 },
230  { 1, 2, 0, 9, 8, 3, 5, 4 },
231  { 1, 8, 5, 2, 0, 4, 3 },
232  { 0, 5, 4, 2, 8, 3, 9, 1 },
233  { 1, 2, 0, 9, 8, 3, 5, 4 },
234  { 0, 3, 9, 8, 5, 4, 2, 1 },
235  { 0, 4, 3, 8, 5, 2, 1 },
236  { 1, 5, 4, 2, 0, 9, 3 },
237  { 1, 9, 5, 2, 0, 4, 3 },
238  { 0, 5, 3, 9, 4, 2, 1 },
239  { 0, 4, 5, 3, 2, 1 },
240  }
241 };
242 
243 typedef struct BlockXY {
244  int w, h;
245  int ax, ay;
246  int x, y;
247  int size;
248  uint8_t *block;
249  int linesize;
250 } BlockXY;
251 
252 typedef struct MotionXY {
253  int x, y;
254 } MotionXY;
255 
256 typedef struct MobiClipContext {
258 
260  int moflex;
263 
265 
266  uint8_t *bitstream;
268 
269  int qtab[2][64];
270  uint8_t pre[32];
273 
276 
277 static VLC rl_vlc[2];
278 static VLC mv_vlc[2][16];
279 
280 static av_cold void mobiclip_init_static(void)
281 {
283  bits0, sizeof(*bits0),
284  syms0, sizeof(*syms0), sizeof(*syms0),
285  0, 0, 1 << MOBI_RL_VLC_BITS);
287  bits0, sizeof(*bits0),
288  syms1, sizeof(*syms1), sizeof(*syms1),
289  0, 0, 1 << MOBI_RL_VLC_BITS);
290  for (int i = 0; i < 2; i++) {
291  static VLCElem vlc_buf[2 * 16 << MOBI_MV_VLC_BITS];
292  for (int j = 0; j < 16; j++) {
293  mv_vlc[i][j].table = &vlc_buf[(16 * i + j) << MOBI_MV_VLC_BITS];
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]),
299  }
300  }
301 }
302 
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 
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].table,
414  MOBI_RL_VLC_BITS, 1);
415 
416  *last = (n >> 11) == 1;
417  *run = (n >> 5) & 0x3F;
418  *level = n & 0x1F;
419 }
420 
422  int bx, int by, int size, int plane)
423 {
424  MobiClipContext *s = avctx->priv_data;
425  GetBitContext *gb = &s->gb;
426  int mat[64] = { 0 };
427  const uint8_t *ztab = size == 8 ? ff_zigzag_direct : zigzag4x4_tab;
428  const int *qtab = s->qtab[size == 8];
429  uint8_t *dst = frame->data[plane] + by * frame->linesize[plane] + bx;
430 
431  for (int pos = 0; get_bits_left(gb) > 0; pos++) {
432  int qval, last, run, level;
433 
434  read_run_encoding(avctx, &last, &run, &level);
435 
436  if (level) {
437  if (get_bits1(gb))
438  level = -level;
439  } else if (!get_bits1(gb)) {
440  read_run_encoding(avctx, &last, &run, &level);
441  level += run_residue[s->dct_tab_idx][(last ? 64 : 0) + run];
442  if (get_bits1(gb))
443  level = -level;
444  } else if (!get_bits1(gb)) {
445  read_run_encoding(avctx, &last, &run, &level);
446  run += run_residue[s->dct_tab_idx][128 + (last ? 64 : 0) + level];
447  if (get_bits1(gb))
448  level = -level;
449  } else {
450  last = get_bits1(gb);
451  run = get_bits(gb, 6);
452  level = get_sbits(gb, 12);
453  }
454 
455  pos += run;
456  if (pos >= size * size)
457  return AVERROR_INVALIDDATA;
458  qval = qtab[pos];
459  mat[ztab[pos]] = qval *(unsigned)level;
460 
461  if (last)
462  break;
463  }
464 
465  mat[0] += 32;
466  for (int y = 0; y < size; y++)
467  idct(&mat[y * size], size);
468 
469  for (int y = 0; y < size; y++) {
470  for (int x = y + 1; x < size; x++) {
471  int a = mat[x * size + y];
472  int b = mat[y * size + x];
473 
474  mat[y * size + x] = a;
475  mat[x * size + y] = b;
476  }
477 
478  idct(&mat[y * size], size);
479  for (int x = 0; x < size; x++)
480  dst[x] = av_clip_uint8(dst[x] + (mat[y * size + x] >> 6));
481  dst += frame->linesize[plane];
482  }
483 
484  return 0;
485 }
486 
488  int bx, int by, int size, int plane)
489 {
490  MobiClipContext *s = avctx->priv_data;
491  GetBitContext *gb = &s->gb;
492  int ret, idx = get_ue_golomb_31(gb);
493 
494  if (idx == 0) {
495  return add_coefficients(avctx, frame, bx, by, size, plane);
496  } else if ((unsigned)idx < FF_ARRAY_ELEMS(pframe_block4x4_coefficients_tab)) {
498 
499  for (int y = by; y < by + 8; y += 4) {
500  for (int x = bx; x < bx + 8; x += 4) {
501  if (flags & 1) {
502  ret = add_coefficients(avctx, frame, x, y, 4, plane);
503  if (ret < 0)
504  return ret;
505  }
506  flags >>= 1;
507  }
508  }
509  return 0;
510  } else {
511  return AVERROR_INVALIDDATA;
512  }
513 }
514 
515 static int adjust(int x, int size)
516 {
517  return size == 16 ? (x + 1) >> 1 : x;
518 }
519 
520 static uint8_t pget(BlockXY b)
521 {
522  BlockXY ret = b;
523  int x, y;
524 
525  if (b.x == -1 && b.y >= b.size) {
526  ret.x = -1, ret.y = b.size - 1;
527  } else if (b.x >= -1 && b.y >= -1) {
528  ret.x = b.x, ret.y = b.y;
529  } else if (b.x == -1 && b.y == -2) {
530  ret.x = 0, ret.y = -1;
531  } else if (b.x == -2 && b.y == -1) {
532  ret.x = -1, ret.y = 0;
533  }
534 
535  y = av_clip(ret.ay + ret.y, 0, ret.h - 1);
536  x = av_clip(ret.ax + ret.x, 0, ret.w - 1);
537 
538  return ret.block[y * ret.linesize + x];
539 }
540 
541 static uint8_t half(int a, int b)
542 {
543  return ((a + b) + 1) / 2;
544 }
545 
546 static uint8_t half3(int a, int b, int c)
547 {
548  return ((a + b + b + c) * 2 / 4 + 1) / 2;
549 }
550 
551 static uint8_t pick_above(BlockXY bxy)
552 {
553  bxy.y = bxy.y - 1;
554 
555  return pget(bxy);
556 }
557 
558 static uint8_t pick_left(BlockXY bxy)
559 {
560  bxy.x = bxy.x - 1;
561 
562  return pget(bxy);
563 }
564 
565 static uint8_t half_horz(BlockXY bxy)
566 {
567  BlockXY a = bxy, b = bxy, c = bxy;
568 
569  a.x -= 1;
570  c.x += 1;
571 
572  return half3(pget(a), pget(b), pget(c));
573 }
574 
575 static uint8_t half_vert(BlockXY bxy)
576 {
577  BlockXY a = bxy, b = bxy, c = bxy;
578 
579  a.y -= 1;
580  c.y += 1;
581 
582  return half3(pget(a), pget(b), pget(c));
583 }
584 
585 static uint8_t pick_4(BlockXY bxy)
586 {
587  int val;
588 
589  if ((bxy.x % 2) == 0) {
590  BlockXY ba, bb;
591  int a, b;
592 
593  ba = bxy;
594  ba.x = -1;
595  ba.y = bxy.y + bxy.x / 2;
596  a = pget(ba);
597 
598  bb = bxy;
599  bb.x = -1;
600  bb.y = bxy.y + bxy.x / 2 + 1;
601  b = pget(bb);
602 
603  val = half(a, b);
604  } else {
605  BlockXY ba;
606 
607  ba = bxy;
608  ba.x = -1;
609  ba.y = bxy.y + bxy.x / 2 + 1;
610  val = half_vert(ba);
611  }
612 
613  return val;
614 }
615 
616 static uint8_t pick_5(BlockXY bxy)
617 {
618  int val;
619 
620  if (bxy.x == 0) {
621  BlockXY a = bxy;
622  BlockXY b = bxy;
623 
624  a.x = -1;
625  a.y -= 1;
626 
627  b.x = -1;
628 
629  val = half(pget(a), pget(b));
630  } else if (bxy.y == 0) {
631  BlockXY a = bxy;
632 
633  a.x -= 2;
634  a.y -= 1;
635 
636  val = half_horz(a);
637  } else if (bxy.x == 1) {
638  BlockXY a = bxy;
639 
640  a.x -= 2;
641  a.y -= 1;
642 
643  val = half_vert(a);
644  } else {
645  BlockXY a = bxy;
646 
647  a.x -= 2;
648  a.y -= 1;
649 
650  val = pget(a);
651  }
652 
653  return val;
654 }
655 
656 static uint8_t pick_6(BlockXY bxy)
657 {
658  int val;
659 
660  if (bxy.y == 0) {
661  BlockXY a = bxy;
662  BlockXY b = bxy;
663 
664  a.x -= 1;
665  a.y = -1;
666 
667  b.y = -1;
668 
669  val = half(pget(a), pget(b));
670  } else if (bxy.x == 0) {
671  BlockXY a = bxy;
672 
673  a.x -= 1;
674  a.y -= 2;
675 
676  val = half_vert(a);
677  } else if (bxy.y == 1) {
678  BlockXY a = bxy;
679 
680  a.x -= 1;
681  a.y -= 2;
682 
683  val = half_horz(a);
684  } else {
685  BlockXY a = bxy;
686 
687  a.x -= 1;
688  a.y -= 2;
689 
690  val = pget(a);
691  }
692 
693  return val;
694 }
695 
696 static uint8_t pick_7(BlockXY bxy)
697 {
698  int clr, acc1, acc2;
699  BlockXY a = bxy;
700 
701  a.x -= 1;
702  a.y -= 1;
703  clr = pget(a);
704  if (bxy.x && bxy.y)
705  return clr;
706 
707  if (bxy.x == 0) {
708  a.x = -1;
709  a.y = bxy.y;
710  } else {
711  a.x = bxy.x - 2;
712  a.y = -1;
713  }
714  acc1 = pget(a);
715 
716  if (bxy.y == 0) {
717  a.x = bxy.x;
718  a.y = -1;
719  } else {
720  a.x = -1;
721  a.y = bxy.y - 2;
722  }
723  acc2 = pget(a);
724 
725  return half3(acc1, clr, acc2);
726 }
727 
728 static uint8_t pick_8(BlockXY bxy)
729 {
730  BlockXY ba = bxy;
731  BlockXY bb = bxy;
732  int val;
733 
734  if (bxy.y == 0) {
735  int a, b;
736 
737  ba.y = -1;
738  a = pget(ba);
739 
740  bb.x += 1;
741  bb.y = -1;
742 
743  b = pget(bb);
744 
745  val = half(a, b);
746  } else if (bxy.y == 1) {
747  ba.x += 1;
748  ba.y -= 2;
749 
750  val = half_horz(ba);
751  } else if (bxy.x < bxy.size - 1) {
752  ba.x += 1;
753  ba.y -= 2;
754 
755  val = pget(ba);
756  } else if (bxy.y % 2 == 0) {
757  int a, b;
758 
759  ba.x = bxy.y / 2 + bxy.size - 1;
760  ba.y = -1;
761  a = pget(ba);
762 
763  bb.x = bxy.y / 2 + bxy.size;
764  bb.y = -1;
765 
766  b = pget(bb);
767 
768  val = half(a, b);
769  } else {
770  ba.x = bxy.y / 2 + bxy.size;
771  ba.y = -1;
772 
773  val = half_horz(ba);
774  }
775 
776  return val;
777 }
778 
779 static void block_fill_simple(uint8_t *block, int size, int linesize, int fill)
780 {
781  for (int y = 0; y < size; y++) {
782  memset(block, fill, size);
783  block += linesize;
784  }
785 }
786 
787 static void block_fill(uint8_t *block, int size, int linesize,
788  int w, int h, int ax, int ay,
789  uint8_t (*pick)(BlockXY bxy))
790 {
791  BlockXY bxy;
792 
793  bxy.size = size;
794  bxy.block = block;
795  bxy.linesize = linesize;
796  bxy.w = w;
797  bxy.h = h;
798  bxy.ay = ay;
799  bxy.ax = ax;
800 
801  for (int y = 0; y < size; y++) {
802  bxy.y = y;
803  for (int x = 0; x < size; x++) {
804  uint8_t val;
805 
806  bxy.x = x;
807 
808  val = pick(bxy);
809 
810  block[ax + x + (ay + y) * linesize] = val;
811  }
812  }
813 }
814 
815 static int block_sum(const uint8_t *block, int w, int h, int linesize)
816 {
817  int sum = 0;
818 
819  for (int y = 0; y < h; y++) {
820  for (int x = 0; x < w; x++) {
821  sum += block[x];
822  }
823  block += linesize;
824  }
825 
826  return sum;
827 }
828 
829 static int predict_intra(AVCodecContext *avctx, AVFrame *frame, int ax, int ay,
830  int pmode, int add_coeffs, int size, int plane)
831 {
832  MobiClipContext *s = avctx->priv_data;
833  GetBitContext *gb = &s->gb;
834  int w = avctx->width >> !!plane, h = avctx->height >> !!plane;
835  int ret = 0;
836 
837  switch (pmode) {
838  case 0:
839  block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_above);
840  break;
841  case 1:
842  block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_left);
843  break;
844  case 2:
845  {
846  int arr1[16];
847  int arr2[16];
848  uint8_t *top = frame->data[plane] + FFMAX(ay - 1, 0) * frame->linesize[plane] + ax;
849  uint8_t *left = frame->data[plane] + ay * frame->linesize[plane] + FFMAX(ax - 1, 0);
850  int bottommost = frame->data[plane][(ay + size - 1) * frame->linesize[plane] + FFMAX(ax - 1, 0)];
851  int rightmost = frame->data[plane][FFMAX(ay - 1, 0) * frame->linesize[plane] + ax + size - 1];
852  int avg = (bottommost + rightmost + 1) / 2 + 2 * av_clip(get_se_golomb(gb), -(1<<16), 1<<16);
853  int r6 = adjust(avg - bottommost, size);
854  int r9 = adjust(avg - rightmost, size);
855  int shift = adjust(size, size) == 8 ? 3 : 2;
856  uint8_t *block;
857 
858  for (int x = 0; x < size; x++) {
859  int val = top[x];
860  arr1[x] = adjust(((bottommost - val) * (1 << shift)) + r6 * (x + 1), size);
861  }
862 
863  for (int y = 0; y < size; y++) {
864  int val = left[y * frame->linesize[plane]];
865  arr2[y] = adjust(((rightmost - val) * (1 << shift)) + r9 * (y + 1), size);
866  }
867 
868  block = frame->data[plane] + ay * frame->linesize[plane] + ax;
869  for (int y = 0; y < size; y++) {
870  for (int x = 0; x < size; x++) {
871  block[x] = (((top[x] + left[0] + ((arr1[x] * (y + 1) +
872  arr2[y] * (x + 1)) >> 2 * shift)) + 1) / 2) & 0xFF;
873  }
874  block += frame->linesize[plane];
875  left += frame->linesize[plane];
876  }
877  }
878  break;
879  case 3:
880  {
881  uint8_t fill;
882 
883  if (ax == 0 && ay == 0) {
884  fill = 0x80;
885  } else if (ax >= 1 && ay >= 1) {
886  int left = block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1,
887  1, size, frame->linesize[plane]);
888  int top = block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax,
889  size, 1, frame->linesize[plane]);
890 
891  fill = ((left + top) * 2 / (2 * size) + 1) / 2;
892  } else if (ax >= 1) {
893  fill = (block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1,
894  1, size, frame->linesize[plane]) * 2 / size + 1) / 2;
895  } else if (ay >= 1) {
896  fill = (block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax,
897  size, 1, frame->linesize[plane]) * 2 / size + 1) / 2;
898  } else {
899  return -1;
900  }
901 
902  block_fill_simple(frame->data[plane] + ay * frame->linesize[plane] + ax,
903  size, frame->linesize[plane], fill);
904  }
905  break;
906  case 4:
907  block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_4);
908  break;
909  case 5:
910  block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_5);
911  break;
912  case 6:
913  block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_6);
914  break;
915  case 7:
916  block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_7);
917  break;
918  case 8:
919  block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_8);
920  break;
921  }
922 
923  if (add_coeffs)
924  ret = add_coefficients(avctx, frame, ax, ay, size, plane);
925 
926  return ret;
927 }
928 
929 static int get_prediction(AVCodecContext *avctx, int x, int y, int size)
930 {
931  MobiClipContext *s = avctx->priv_data;
932  GetBitContext *gb = &s->gb;
933  int index = (y & 0xC) | (x / 4 % 4);
934 
935  uint8_t val = FFMIN(s->pre[index], index % 4 == 0 ? 9 : s->pre[index + 3]);
936  if (val == 9)
937  val = 3;
938 
939  if (!get_bits1(gb)) {
940  int x = get_bits(gb, 3);
941  val = x + (x >= val ? 1 : 0);
942  }
943 
944  s->pre[index + 4] = val;
945  if (size == 8)
946  s->pre[index + 5] = s->pre[index + 8] = s->pre[index + 9] = val;
947 
948  return val;
949 }
950 
952  int x, int y, int pmode, int has_coeffs, int plane)
953 {
954  MobiClipContext *s = avctx->priv_data;
955  GetBitContext *gb = &s->gb;
956  int tmp, ret;
957 
958  if (!has_coeffs) {
959  if (pmode < 0)
960  pmode = get_prediction(avctx, x, y, 8);
961  return predict_intra(avctx, frame, x, y, pmode, 0, 8, plane);
962  }
963 
964  tmp = get_ue_golomb_31(gb);
966  return AVERROR_INVALIDDATA;
967 
968  if (tmp == 0) {
969  if (pmode < 0)
970  pmode = get_prediction(avctx, x, y, 8);
971  ret = predict_intra(avctx, frame, x, y, pmode, 1, 8, plane);
972  } else {
974 
975  for (int by = y; by < y + 8; by += 4) {
976  for (int bx = x; bx < x + 8; bx += 4) {
977  int new_pmode = pmode;
978 
979  if (new_pmode < 0)
980  new_pmode = get_prediction(avctx, bx, by, 4);
981  ret = predict_intra(avctx, frame, bx, by, new_pmode, flags & 1, 4, plane);
982  if (ret < 0)
983  return ret;
984  flags >>= 1;
985  }
986  }
987  }
988 
989  return ret;
990 }
991 
993  int x, int y, int predict)
994 {
995  MobiClipContext *s = avctx->priv_data;
996  GetBitContext *gb = &s->gb;
997  int flags, pmode_uv, idx = get_ue_golomb(gb);
998  int ret = 0;
999 
1000  if (idx < 0 || idx >= FF_ARRAY_ELEMS(block8x8_coefficients_tab))
1001  return AVERROR_INVALIDDATA;
1002 
1004 
1005  if (predict) {
1006  ret = process_block(avctx, frame, x, y, -1, flags & 1, 0);
1007  if (ret < 0)
1008  return ret;
1009  flags >>= 1;
1010  ret = process_block(avctx, frame, x + 8, y, -1, flags & 1, 0);
1011  if (ret < 0)
1012  return ret;
1013  flags >>= 1;
1014  ret = process_block(avctx, frame, x, y + 8, -1, flags & 1, 0);
1015  if (ret < 0)
1016  return ret;
1017  flags >>= 1;
1018  ret = process_block(avctx, frame, x + 8, y + 8, -1, flags & 1, 0);
1019  if (ret < 0)
1020  return ret;
1021  flags >>= 1;
1022  } else {
1023  int pmode = get_bits(gb, 3);
1024 
1025  if (pmode == 2) {
1026  ret = predict_intra(avctx, frame, x, y, pmode, 0, 16, 0);
1027  if (ret < 0)
1028  return ret;
1029  pmode = 9;
1030  }
1031 
1032  ret = process_block(avctx, frame, x, y, pmode, flags & 1, 0);
1033  if (ret < 0)
1034  return ret;
1035  flags >>= 1;
1036  ret = process_block(avctx, frame, x + 8, y, pmode, flags & 1, 0);
1037  if (ret < 0)
1038  return ret;
1039  flags >>= 1;
1040  ret = process_block(avctx, frame, x, y + 8, pmode, flags & 1, 0);
1041  if (ret < 0)
1042  return ret;
1043  flags >>= 1;
1044  ret = process_block(avctx, frame, x + 8, y + 8, pmode, flags & 1, 0);
1045  if (ret < 0)
1046  return ret;
1047  flags >>= 1;
1048  }
1049 
1050  pmode_uv = get_bits(gb, 3);
1051  if (pmode_uv == 2) {
1052  ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 1 + !s->moflex);
1053  if (ret < 0)
1054  return ret;
1055  ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 2 - !s->moflex);
1056  if (ret < 0)
1057  return ret;
1058  pmode_uv = 9;
1059  }
1060 
1061  ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 1 + !s->moflex);
1062  if (ret < 0)
1063  return ret;
1064  flags >>= 1;
1065  ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 2 - !s->moflex);
1066  if (ret < 0)
1067  return ret;
1068 
1069  return 0;
1070 }
1071 
1072 static int get_index(int x)
1073 {
1074  return x == 16 ? 0 : x == 8 ? 1 : x == 4 ? 2 : x == 2 ? 3 : 0;
1075 }
1076 
1077 static int predict_motion(AVCodecContext *avctx,
1078  int width, int height, int index,
1079  int offsetm, int offsetx, int offsety)
1080 {
1081  MobiClipContext *s = avctx->priv_data;
1082  MotionXY *motion = s->motion;
1083  GetBitContext *gb = &s->gb;
1084  int fheight = avctx->height;
1085  int fwidth = avctx->width;
1086 
1087  if (index <= 5) {
1088  int sidx = -FFMAX(1, index) + s->current_pic;
1089  MotionXY mv = s->motion[0];
1090 
1091  if (sidx < 0)
1092  sidx += 6;
1093 
1094  if (index > 0) {
1095  mv.x = mv.x + (unsigned)get_se_golomb(gb);
1096  mv.y = mv.y + (unsigned)get_se_golomb(gb);
1097  }
1098  if (mv.x >= INT_MAX || mv.y >= INT_MAX)
1099  return AVERROR_INVALIDDATA;
1100 
1101  motion[offsetm].x = mv.x;
1102  motion[offsetm].y = mv.y;
1103 
1104  for (int i = 0; i < 3; i++) {
1105  int method, src_linesize, dst_linesize;
1106  uint8_t *src, *dst;
1107 
1108  if (i == 1) {
1109  offsetx = offsetx >> 1;
1110  offsety = offsety >> 1;
1111  mv.x = mv.x >> 1;
1112  mv.y = mv.y >> 1;
1113  width = width >> 1;
1114  height = height >> 1;
1115  fwidth = fwidth >> 1;
1116  fheight = fheight >> 1;
1117  }
1118 
1119  av_assert0(s->pic[sidx]);
1120  av_assert0(s->pic[s->current_pic]);
1121  av_assert0(s->pic[s->current_pic]->data[i]);
1122  if (!s->pic[sidx]->data[i])
1123  return AVERROR_INVALIDDATA;
1124 
1125  method = (mv.x & 1) | ((mv.y & 1) << 1);
1126  src_linesize = s->pic[sidx]->linesize[i];
1127  dst_linesize = s->pic[s->current_pic]->linesize[i];
1128  dst = s->pic[s->current_pic]->data[i] + offsetx + offsety * dst_linesize;
1129 
1130  if (offsetx + (mv.x >> 1) < 0 ||
1131  offsety + (mv.y >> 1) < 0 ||
1132  offsetx + width + (mv.x + 1 >> 1) > fwidth ||
1133  offsety + height + (mv.y + 1 >> 1) > fheight)
1134  return AVERROR_INVALIDDATA;
1135 
1136  switch (method) {
1137  case 0:
1138  src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1139  (offsety + (mv.y >> 1)) * src_linesize;
1140  for (int y = 0; y < height; y++) {
1141  for (int x = 0; x < width; x++)
1142  dst[x] = src[x];
1143  dst += dst_linesize;
1144  src += src_linesize;
1145  }
1146  break;
1147  case 1:
1148  src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1149  (offsety + (mv.y >> 1)) * src_linesize;
1150  for (int y = 0; y < height; y++) {
1151  for (int x = 0; x < width; x++) {
1152  dst[x] = (uint8_t)((src[x] >> 1) + (src[x + 1] >> 1));
1153  }
1154 
1155  dst += dst_linesize;
1156  src += src_linesize;
1157  }
1158  break;
1159  case 2:
1160  src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1161  (offsety + (mv.y >> 1)) * src_linesize;
1162  for (int y = 0; y < height; y++) {
1163  for (int x = 0; x < width; x++) {
1164  dst[x] = (uint8_t)((src[x] >> 1) + (src[x + src_linesize] >> 1));
1165  }
1166 
1167  dst += dst_linesize;
1168  src += src_linesize;
1169  }
1170  break;
1171  case 3:
1172  src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) +
1173  (offsety + (mv.y >> 1)) * src_linesize;
1174  for (int y = 0; y < height; y++) {
1175  for (int x = 0; x < width; x++) {
1176  dst[x] = (uint8_t)((((src[x] >> 1) + (src[x + 1] >> 1)) >> 1) +
1177  (((src[x + src_linesize] >> 1) + (src[x + 1 + src_linesize] >> 1)) >> 1));
1178  }
1179 
1180  dst += dst_linesize;
1181  src += src_linesize;
1182  }
1183  break;
1184  }
1185  }
1186  } else {
1187  int tidx;
1188  int adjx = index == 8 ? 0 : width / 2;
1189  int adjy = index == 8 ? height / 2 : 0;
1190 
1191  width = width - adjx;
1192  height = height - adjy;
1193  tidx = get_index(height) * 4 + get_index(width);
1194 
1195  for (int i = 0; i < 2; i++) {
1196  int ret, idx2;
1197 
1198  idx2 = get_vlc2(gb, mv_vlc[s->moflex][tidx].table,
1199  MOBI_MV_VLC_BITS, 1);
1200 
1201  ret = predict_motion(avctx, width, height, idx2,
1202  offsetm, offsetx + i * adjx, offsety + i * adjy);
1203  if (ret < 0)
1204  return ret;
1205  }
1206  }
1207 
1208  return 0;
1209 }
1210 
1211 static int mobiclip_decode(AVCodecContext *avctx, AVFrame *rframe,
1212  int *got_frame, AVPacket *pkt)
1213 {
1214  MobiClipContext *s = avctx->priv_data;
1215  GetBitContext *gb = &s->gb;
1216  AVFrame *frame = s->pic[s->current_pic];
1217  int ret;
1218 
1219  if (avctx->height/16 * (avctx->width/16) * 2 > 8LL*FFALIGN(pkt->size, 2))
1220  return AVERROR_INVALIDDATA;
1221 
1222  av_fast_padded_malloc(&s->bitstream, &s->bitstream_size,
1223  pkt->size);
1224 
1225  if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0)
1226  return ret;
1227 
1228  s->bdsp.bswap16_buf((uint16_t *)s->bitstream,
1229  (uint16_t *)pkt->data,
1230  (pkt->size + 1) >> 1);
1231 
1232  ret = init_get_bits8(gb, s->bitstream, FFALIGN(pkt->size, 2));
1233  if (ret < 0)
1234  return ret;
1235 
1236  if (get_bits1(gb)) {
1237  frame->pict_type = AV_PICTURE_TYPE_I;
1238  frame->key_frame = 1;
1239  s->moflex = get_bits1(gb);
1240  s->dct_tab_idx = get_bits1(gb);
1241 
1242  ret = setup_qtables(avctx, get_bits(gb, 6));
1243  if (ret < 0)
1244  return ret;
1245 
1246  for (int y = 0; y < avctx->height; y += 16) {
1247  for (int x = 0; x < avctx->width; x += 16) {
1248  ret = decode_macroblock(avctx, frame, x, y, get_bits1(gb));
1249  if (ret < 0)
1250  return ret;
1251  }
1252  }
1253  } else {
1254  MotionXY *motion = s->motion;
1255 
1256  memset(motion, 0, s->motion_size);
1257 
1258  frame->pict_type = AV_PICTURE_TYPE_P;
1259  frame->key_frame = 0;
1260  s->dct_tab_idx = 0;
1261 
1262  ret = setup_qtables(avctx, s->quantizer + (int64_t)get_se_golomb(gb));
1263  if (ret < 0)
1264  return ret;
1265 
1266  for (int y = 0; y < avctx->height; y += 16) {
1267  for (int x = 0; x < avctx->width; x += 16) {
1268  int idx;
1269 
1270  motion[0].x = mid_pred(motion[x / 16 + 1].x, motion[x / 16 + 2].x, motion[x / 16 + 3].x);
1271  motion[0].y = mid_pred(motion[x / 16 + 1].y, motion[x / 16 + 2].y, motion[x / 16 + 3].y);
1272  motion[x / 16 + 2].x = 0;
1273  motion[x / 16 + 2].y = 0;
1274 
1275  idx = get_vlc2(gb, mv_vlc[s->moflex][0].table,
1276  MOBI_MV_VLC_BITS, 1);
1277 
1278  if (idx == 6 || idx == 7) {
1279  ret = decode_macroblock(avctx, frame, x, y, idx == 7);
1280  if (ret < 0)
1281  return ret;
1282  } else {
1283  int flags, idx2;
1284  ret = predict_motion(avctx, 16, 16, idx, x / 16 + 2, x, y);
1285  if (ret < 0)
1286  return ret;
1287  idx2 = get_ue_golomb(gb);
1289  return AVERROR_INVALIDDATA;
1291 
1292  for (int sy = y; sy < y + 16; sy += 8) {
1293  for (int sx = x; sx < x + 16; sx += 8) {
1294  if (flags & 1)
1295  add_pframe_coefficients(avctx, frame, sx, sy, 8, 0);
1296  flags >>= 1;
1297  }
1298  }
1299 
1300  if (flags & 1)
1301  add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 1 + !s->moflex);
1302  flags >>= 1;
1303  if (flags & 1)
1304  add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 2 - !s->moflex);
1305  }
1306  }
1307  }
1308  }
1309 
1310  if (!s->moflex)
1311  avctx->colorspace = AVCOL_SPC_YCGCO;
1312 
1313  s->current_pic = (s->current_pic + 1) % 6;
1314  ret = av_frame_ref(rframe, frame);
1315  if (ret < 0)
1316  return ret;
1317  *got_frame = 1;
1318 
1319  return 0;
1320 }
1321 
1322 static void mobiclip_flush(AVCodecContext *avctx)
1323 {
1324  MobiClipContext *s = avctx->priv_data;
1325 
1326  for (int i = 0; i < 6; i++)
1327  av_frame_unref(s->pic[i]);
1328 }
1329 
1331 {
1332  MobiClipContext *s = avctx->priv_data;
1333 
1334  av_freep(&s->bitstream);
1335  s->bitstream_size = 0;
1336  av_freep(&s->motion);
1337  s->motion_size = 0;
1338 
1339  for (int i = 0; i < 6; i++) {
1340  av_frame_free(&s->pic[i]);
1341  }
1342 
1343  return 0;
1344 }
1345 
1347  .p.name = "mobiclip",
1348  CODEC_LONG_NAME("MobiClip Video"),
1349  .p.type = AVMEDIA_TYPE_VIDEO,
1350  .p.id = AV_CODEC_ID_MOBICLIP,
1351  .priv_data_size = sizeof(MobiClipContext),
1352  .init = mobiclip_init,
1354  .flush = mobiclip_flush,
1355  .close = mobiclip_close,
1356  .p.capabilities = AV_CODEC_CAP_DR1,
1357  .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
1358 };
MobiClipContext::dct_tab_idx
int dct_tab_idx
Definition: mobiclip.c:261
mobiclip_flush
static void mobiclip_flush(AVCodecContext *avctx)
Definition: mobiclip.c:1322
mv_vlc
static VLC mv_vlc[2][16]
Definition: mobiclip.c:278
bswapdsp.h
level
uint8_t level
Definition: svq3.c:204
av_clip
#define av_clip
Definition: common.h:95
MOBI_RL_VLC_BITS
#define MOBI_RL_VLC_BITS
Definition: mobiclip.c:37
FF_CODEC_CAP_INIT_CLEANUP
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
Definition: codec_internal.h:42
get_bits_left
static int get_bits_left(GetBitContext *gb)
Definition: get_bits.h:839
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
pick_7
static uint8_t pick_7(BlockXY bxy)
Definition: mobiclip.c:696
MOBI_MV_VLC_BITS
#define MOBI_MV_VLC_BITS
Definition: mobiclip.c:38
MobiClipContext::pre
uint8_t pre[32]
Definition: mobiclip.c:270
AVCodecContext::colorspace
enum AVColorSpace colorspace
YUV colorspace type.
Definition: avcodec.h:975
thread.h
block_fill_simple
static void block_fill_simple(uint8_t *block, int size, int linesize, int fill)
Definition: mobiclip.c:779
AV_CODEC_ID_MOBICLIP
@ AV_CODEC_ID_MOBICLIP
Definition: codec_id.h:307
pick_left
static uint8_t pick_left(BlockXY bxy)
Definition: mobiclip.c:558
mv
static const int8_t mv[256][2]
Definition: 4xm.c:80
block_sum
static int block_sum(const uint8_t *block, int w, int h, int linesize)
Definition: mobiclip.c:815
setup_qtables
static int setup_qtables(AVCodecContext *avctx, int64_t quantizer)
Definition: mobiclip.c:333
block_fill
static void block_fill(uint8_t *block, int size, int linesize, int w, int h, int ax, int ay, uint8_t(*pick)(BlockXY bxy))
Definition: mobiclip.c:787
mv_bits
static const uint8_t mv_bits[2][16][10]
Definition: mobiclip.c:163
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:116
quant8x8_tab
static const uint8_t quant8x8_tab[][64]
Definition: mobiclip.c:56
half3
static uint8_t half3(int a, int b, int c)
Definition: mobiclip.c:546
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:325
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:28
w
uint8_t w
Definition: llviddspenc.c:38
get_ue_golomb
static int get_ue_golomb(GetBitContext *gb)
Read an unsigned Exp-Golomb code in the range 0 to 8190.
Definition: golomb.h:53
MobiClipContext
Definition: mobiclip.c:256
MobiClipContext::quantizer
int quantizer
Definition: mobiclip.c:262
AVPacket::data
uint8_t * data
Definition: packet.h:374
pframe_block4x4_coefficients_tab
static const uint8_t pframe_block4x4_coefficients_tab[]
Definition: mobiclip.c:77
MobiClipContext::moflex
int moflex
Definition: mobiclip.c:260
b
#define b
Definition: input.c:41
half
static uint8_t half(int a, int b)
Definition: mobiclip.c:541
MobiClipContext::qtab
int qtab[2][64]
Definition: mobiclip.c:269
FFCodec
Definition: codec_internal.h:119
BlockXY::linesize
int linesize
Definition: mobiclip.c:249
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
MobiClipContext::motion
MotionXY * motion
Definition: mobiclip.c:271
golomb.h
exp golomb vlc stuff
pframe_block8x8_coefficients_tab
static const uint8_t pframe_block8x8_coefficients_tab[]
Definition: mobiclip.c:92
get_bits
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:379
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:123
pick_5
static uint8_t pick_5(BlockXY bxy)
Definition: mobiclip.c:616
syms1
static const uint16_t syms1[]
Definition: mobiclip.c:147
GetBitContext
Definition: get_bits.h:61
val
static double val(void *priv, double ch)
Definition: aeval.c:77
MobiClipContext::current_pic
int current_pic
Definition: mobiclip.c:259
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:104
avassert.h
ff_thread_once
static int ff_thread_once(char *control, void(*routine)(void))
Definition: thread.h:184
pkt
AVPacket * pkt
Definition: movenc.c:59
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_cold
#define av_cold
Definition: attributes.h:90
BlockXY::ay
int ay
Definition: mobiclip.c:245
init_get_bits8
static int init_get_bits8(GetBitContext *s, const uint8_t *buffer, int byte_size)
Initialize GetBitContext.
Definition: get_bits.h:667
width
#define width
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:298
s
#define s(width, name)
Definition: cbs_vp9.c:256
quant4x4_tab
static const uint8_t quant4x4_tab[][16]
Definition: mobiclip.c:46
adjust
static int adjust(int x, int size)
Definition: mobiclip.c:515
g
const char * g
Definition: vf_curves.c:127
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts_bsf.c:363
BlockXY::block
uint8_t * block
Definition: mobiclip.c:248
vlc_buf
static VLCElem vlc_buf[16716]
Definition: clearvideo.c:80
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
get_sbits
static int get_sbits(GetBitContext *s, int n)
Definition: get_bits.h:359
MotionXY
Definition: mobiclip.c:252
decode.h
get_bits.h
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
get_se_golomb
static int get_se_golomb(GetBitContext *gb)
read signed exp golomb code.
Definition: golomb.h:239
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:264
mobiclip_close
static av_cold int mobiclip_close(AVCodecContext *avctx)
Definition: mobiclip.c:1330
syms0
static const uint16_t syms0[]
Definition: mobiclip.c:134
AV_ONCE_INIT
#define AV_ONCE_INIT
Definition: thread.h:182
ff_bswapdsp_init
av_cold void ff_bswapdsp_init(BswapDSPContext *c)
Definition: bswapdsp.c:49
NULL
#define NULL
Definition: coverity.c:32
run
uint8_t run
Definition: svq3.c:203
INIT_VLC_STATIC_FROM_LENGTHS
#define INIT_VLC_STATIC_FROM_LENGTHS(vlc, bits, nb_codes, lens, len_wrap, symbols, symbols_wrap, symbols_size, offset, flags, static_size)
Definition: vlc.h:131
AV_PICTURE_TYPE_I
@ AV_PICTURE_TYPE_I
Intra.
Definition: avutil.h:274
get_bits1
static unsigned int get_bits1(GetBitContext *s)
Definition: get_bits.h:498
ff_init_vlc_from_lengths
int ff_init_vlc_from_lengths(VLC *vlc, int nb_bits, int nb_codes, const int8_t *lens, int lens_wrap, const void *symbols, int symbols_wrap, int symbols_size, int offset, int flags, void *logctx)
Build VLC decoding tables suitable for use with get_vlc2()
Definition: vlc.c:328
mathops.h
INIT_VLC_USE_NEW_STATIC
#define INIT_VLC_USE_NEW_STATIC
Definition: vlc.h:100
predict_intra
static int predict_intra(AVCodecContext *avctx, AVFrame *frame, int ax, int ay, int pmode, int add_coeffs, int size, int plane)
Definition: mobiclip.c:829
AVCOL_SPC_YCGCO
@ AVCOL_SPC_YCGCO
used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16
Definition: pixfmt.h:596
get_vlc2
static av_always_inline int get_vlc2(GetBitContext *s, const VLCElem *table, int bits, int max_depth)
Parse a vlc code.
Definition: get_bits.h:787
AVOnce
#define AVOnce
Definition: thread.h:181
index
int index
Definition: gxfenc.c:89
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
MobiClipContext::pic
AVFrame * pic[6]
Definition: mobiclip.c:257
VLC::table_allocated
int table_allocated
Definition: vlc.h:34
f
f
Definition: af_crystalizer.c:122
AV_CODEC_CAP_DR1
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:52
mv_len
static const uint8_t mv_len[16]
Definition: mobiclip.c:158
AVPacket::size
int size
Definition: packet.h:375
av_frame_ref
int av_frame_ref(AVFrame *dst, const AVFrame *src)
Set up a new reference to the data described by the source frame.
Definition: frame.c:353
codec_internal.h
shift
static int shift(int a, int b)
Definition: bonk.c:253
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:425
get_index
static int get_index(int x)
Definition: mobiclip.c:1072
size
int size
Definition: twinvq_data.h:10344
BlockXY::x
int x
Definition: mobiclip.c:246
VLCElem
Definition: vlc.h:27
ff_mobiclip_decoder
const FFCodec ff_mobiclip_decoder
Definition: mobiclip.c:1346
avg
#define avg(a, b, c, d)
Definition: colorspacedsp_template.c:28
decode_macroblock
static int decode_macroblock(AVCodecContext *avctx, AVFrame *frame, int x, int y, int predict)
Definition: mobiclip.c:992
BlockXY::size
int size
Definition: mobiclip.c:247
BlockXY::w
int w
Definition: mobiclip.c:244
run_residue
static const uint8_t run_residue[2][256]
Definition: mobiclip.c:100
predict_motion
static int predict_motion(AVCodecContext *avctx, int width, int height, int index, int offsetm, int offsetx, int offsety)
Definition: mobiclip.c:1077
height
#define height
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
BlockXY::h
int h
Definition: mobiclip.c:244
half_horz
static uint8_t half_horz(BlockXY bxy)
Definition: mobiclip.c:565
MotionXY::x
int x
Definition: mobiclip.c:253
get_prediction
static int get_prediction(AVCodecContext *avctx, int x, int y, int size)
Definition: mobiclip.c:929
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
pick_8
static uint8_t pick_8(BlockXY bxy)
Definition: mobiclip.c:728
predict
static av_always_inline void predict(PredictorState *ps, float *coef, int output_enable)
Definition: aacdec.c:176
av_fast_padded_malloc
void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size)
Same behaviour av_fast_malloc but the buffer has additional AV_INPUT_BUFFER_PADDING_SIZE at the end w...
Definition: utils.c:49
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
block8x8_coefficients_tab
static const uint8_t block8x8_coefficients_tab[]
Definition: mobiclip.c:82
pick_above
static uint8_t pick_above(BlockXY bxy)
Definition: mobiclip.c:551
av_frame_unref
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:487
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:211
MobiClipContext::gb
GetBitContext gb
Definition: mobiclip.c:264
pick_6
static uint8_t pick_6(BlockXY bxy)
Definition: mobiclip.c:656
AVCodecContext::height
int height
Definition: avcodec.h:571
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:608
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:272
mobiclip_decode
static int mobiclip_decode(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *pkt)
Definition: mobiclip.c:1211
avcodec.h
ff_zigzag_direct
const uint8_t ff_zigzag_direct[64]
Definition: mathtables.c:98
mid_pred
#define mid_pred
Definition: mathops.h:98
BlockXY::y
int y
Definition: mobiclip.c:246
ff_reget_buffer
int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Identical in function to ff_get_buffer(), except it reuses the existing buffer if available.
Definition: decode.c:1568
ret
ret
Definition: filter_design.txt:187
bits0
static const uint8_t bits0[]
Definition: mobiclip.c:124
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
read_run_encoding
static void read_run_encoding(AVCodecContext *avctx, int *last, int *run, int *level)
Definition: mobiclip.c:408
add_pframe_coefficients
static int add_pframe_coefficients(AVCodecContext *avctx, AVFrame *frame, int bx, int by, int size, int plane)
Definition: mobiclip.c:487
pos
unsigned int pos
Definition: spdifenc.c:412
left
Tag MUST be and< 10hcoeff half pel interpolation filter coefficients, hcoeff[0] are the 2 middle coefficients[1] are the next outer ones and so on, resulting in a filter like:...eff[2], hcoeff[1], hcoeff[0], hcoeff[0], hcoeff[1], hcoeff[2] ... the sign of the coefficients is not explicitly stored but alternates after each coeff and coeff[0] is positive, so ...,+,-,+,-,+,+,-,+,-,+,... hcoeff[0] is not explicitly stored but found by subtracting the sum of all stored coefficients with signs from 32 hcoeff[0]=32 - hcoeff[1] - hcoeff[2] - ... a good choice for hcoeff and htaps is htaps=6 hcoeff={40,-10, 2} an alternative which requires more computations at both encoder and decoder side and may or may not be better is htaps=8 hcoeff={42,-14, 6,-2}ref_frames minimum of the number of available reference frames and max_ref_frames for example the first frame after a key frame always has ref_frames=1spatial_decomposition_type wavelet type 0 is a 9/7 symmetric compact integer wavelet 1 is a 5/3 symmetric compact integer wavelet others are reserved stored as delta from last, last is reset to 0 if always_reset||keyframeqlog quality(logarithmic quantizer scale) stored as delta from last, last is reset to 0 if always_reset||keyframemv_scale stored as delta from last, last is reset to 0 if always_reset||keyframe FIXME check that everything works fine if this changes between framesqbias dequantization bias stored as delta from last, last is reset to 0 if always_reset||keyframeblock_max_depth maximum depth of the block tree stored as delta from last, last is reset to 0 if always_reset||keyframequant_table quantization tableHighlevel bitstream structure:==============================--------------------------------------------|Header|--------------------------------------------|------------------------------------|||Block0||||split?||||yes no||||......... intra?||||:Block01 :yes no||||:Block02 :....... ..........||||:Block03 ::y DC ::ref index:||||:Block04 ::cb DC ::motion x :||||......... :cr DC ::motion y :||||....... ..........|||------------------------------------||------------------------------------|||Block1|||...|--------------------------------------------|------------ ------------ ------------|||Y subbands||Cb subbands||Cr subbands||||--- ---||--- ---||--- ---|||||LL0||HL0||||LL0||HL0||||LL0||HL0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||LH0||HH0||||LH0||HH0||||LH0||HH0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HL1||LH1||||HL1||LH1||||HL1||LH1|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HH1||HL2||||HH1||HL2||||HH1||HL2|||||...||...||...|||------------ ------------ ------------|--------------------------------------------Decoding process:=================------------|||Subbands|------------||||------------|Intra DC||||LL0 subband prediction ------------|\ Dequantization ------------------- \||Reference frames|\ IDWT|------- -------|Motion \|||Frame 0||Frame 1||Compensation . OBMC v -------|------- -------|--------------. \------> Frame n output Frame Frame<----------------------------------/|...|------------------- Range Coder:============Binary Range Coder:------------------- The implemented range coder is an adapted version based upon "Range encoding: an algorithm for removing redundancy from a digitised message." by G. N. N. Martin. The symbols encoded by the Snow range coder are bits(0|1). The associated probabilities are not fix but change depending on the symbol mix seen so far. bit seen|new state ---------+----------------------------------------------- 0|256 - state_transition_table[256 - old_state];1|state_transition_table[old_state];state_transition_table={ 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202, 202, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 215, 215, 216, 217, 218, 219, 220, 220, 222, 223, 224, 225, 226, 227, 227, 229, 229, 230, 231, 232, 234, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 0, 0, 0, 0, 0, 0, 0};FIXME Range Coding of integers:------------------------- FIXME Neighboring Blocks:===================left and top are set to the respective blocks unless they are outside of the image in which case they are set to the Null block top-left is set to the top left block unless it is outside of the image in which case it is set to the left block if this block has no larger parent block or it is at the left side of its parent block and the top right block is not outside of the image then the top right block is used for top-right else the top-left block is used Null block y, cb, cr are 128 level, ref, mx and my are 0 Motion Vector Prediction:=========================1. the motion vectors of all the neighboring blocks are scaled to compensate for the difference of reference frames scaled_mv=(mv *(256 *(current_reference+1)/(mv.reference+1))+128)> the median of the scaled left
Definition: snow.txt:386
half_vert
static uint8_t half_vert(BlockXY bxy)
Definition: mobiclip.c:575
MobiClipContext::bdsp
BswapDSPContext bdsp
Definition: mobiclip.c:274
AVCodecContext
main external API structure.
Definition: avcodec.h:398
get_ue_golomb_31
static int get_ue_golomb_31(GetBitContext *gb)
read unsigned exp golomb code, constraint to a max of 31.
Definition: golomb.h:120
process_block
static int process_block(AVCodecContext *avctx, AVFrame *frame, int x, int y, int pmode, int has_coeffs, int plane)
Definition: mobiclip.c:951
VLC
Definition: vlc.h:31
mobiclip_init_static
static av_cold void mobiclip_init_static(void)
Definition: mobiclip.c:280
inverse4
static void inverse4(unsigned *rs)
Definition: mobiclip.c:358
block4x4_coefficients_tab
static const uint8_t block4x4_coefficients_tab[]
Definition: mobiclip.c:72
VLC::table
VLCElem * table
Definition: vlc.h:33
zigzag4x4_tab
static const uint8_t zigzag4x4_tab[]
Definition: mobiclip.c:40
BlockXY
Definition: mobiclip.c:243
av_clip_uint8
#define av_clip_uint8
Definition: common.h:101
mobiclip_init
static av_cold int mobiclip_init(AVCodecContext *avctx)
Definition: mobiclip.c:303
pget
static uint8_t pget(BlockXY b)
Definition: mobiclip.c:520
AV_PICTURE_TYPE_P
@ AV_PICTURE_TYPE_P
Predicted.
Definition: avutil.h:275
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
MotionXY::y
int y
Definition: mobiclip.c:253
pick_4
static uint8_t pick_4(BlockXY bxy)
Definition: mobiclip.c:585
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AVPacket
This structure stores compressed data.
Definition: packet.h:351
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:425
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
idct
static void idct(int *arr, int size)
Definition: mobiclip.c:371
d
d
Definition: ffmpeg_filter.c:156
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:571
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
block
The exact code depends on how similar the blocks are and how related they are to the block
Definition: filter_design.txt:207
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
BswapDSPContext
Definition: bswapdsp.h:24
h
h
Definition: vp9dsp_template.c:2038
MobiClipContext::motion_size
int motion_size
Definition: mobiclip.c:272
int
int
Definition: ffmpeg_filter.c:156
add_coefficients
static int add_coefficients(AVCodecContext *avctx, AVFrame *frame, int bx, int by, int size, int plane)
Definition: mobiclip.c:421
MobiClipContext::bitstream
uint8_t * bitstream
Definition: mobiclip.c:266
MobiClipContext::bitstream_size
int bitstream_size
Definition: mobiclip.c:267
mv_syms
static const uint8_t mv_syms[2][16][10]
Definition: mobiclip.c:203
BlockXY::ax
int ax
Definition: mobiclip.c:245
rl_vlc
static VLC rl_vlc[2]
Definition: mobiclip.c:277