FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/msmpeg4.c
Date: 2026-04-30 18:27:06
Exec Total Coverage
Lines: 101 148 68.2%
Functions: 5 6 83.3%
Branches: 39 69 56.5%

Line Branch Exec Source
1 /*
2 * MSMPEG4 backend for encoder and decoder
3 * Copyright (c) 2001 Fabrice Bellard
4 * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
5 *
6 * msmpeg4v1 & v2 stuff by Michael Niedermayer <michaelni@gmx.at>
7 *
8 * This file is part of FFmpeg.
9 *
10 * FFmpeg is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * FFmpeg is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with FFmpeg; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 /**
26 * @file
27 * MSMPEG4 backend for encoder and decoder
28 */
29
30 #include "config.h"
31 #include "config_components.h"
32
33 #include "libavutil/attributes.h"
34 #include "libavutil/avassert.h"
35 #include "libavutil/thread.h"
36 #if ARCH_X86
37 #include "libavutil/x86/asm.h"
38 #endif
39
40 #include "avcodec.h"
41 #include "idctdsp.h"
42 #include "mathops.h"
43 #include "mpegvideo.h"
44 #include "msmpeg4.h"
45 #include "mpeg4videodata.h"
46 #include "msmpeg4data.h"
47 #include "msmpeg4_vc1_data.h"
48 #include "wmv2dsp.h"
49
50 /*
51 * You can also call this codec: MPEG-4 with a twist!
52 *
53 * TODO:
54 * - (encoding) select best mv table (two choices)
55 * - (encoding) select best vlc/dc table
56 */
57
58 /* This table is practically identical to the one from H.263
59 * except that it is inverted. */
60 43 static av_cold void init_h263_dc_for_msmpeg4(void)
61 {
62
2/2
✓ Branch 0 taken 22016 times.
✓ Branch 1 taken 43 times.
22059 for (int level = -256; level < 256; level++) {
63 int uni_code, uni_len;
64 int size, v, l;
65 /* find number of bits */
66 22016 size = 0;
67 22016 v = abs(level);
68
2/2
✓ Branch 0 taken 154585 times.
✓ Branch 1 taken 22016 times.
176601 while (v) {
69 154585 v >>= 1;
70 154585 size++;
71 }
72
73
2/2
✓ Branch 0 taken 11008 times.
✓ Branch 1 taken 11008 times.
22016 if (level < 0)
74 11008 l = (-level) ^ ((1 << size) - 1);
75 else
76 11008 l = level;
77
78 /* luminance H.263 */
79 22016 uni_code = ff_mpeg4_DCtab_lum[size][0];
80 22016 uni_len = ff_mpeg4_DCtab_lum[size][1];
81 22016 uni_code ^= (1 << uni_len) - 1; //M$ does not like compatibility
82
83
2/2
✓ Branch 0 taken 21973 times.
✓ Branch 1 taken 43 times.
22016 if (size > 0) {
84 21973 uni_code <<= size; uni_code |= l;
85 21973 uni_len += size;
86
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 21930 times.
21973 if (size > 8) {
87 43 uni_code <<= 1; uni_code |= 1;
88 43 uni_len++;
89 }
90 }
91 22016 ff_v2_dc_lum_table[level + 256][0] = uni_code;
92 22016 ff_v2_dc_lum_table[level + 256][1] = uni_len;
93
94 /* chrominance H.263 */
95 22016 uni_code = ff_mpeg4_DCtab_chrom[size][0];
96 22016 uni_len = ff_mpeg4_DCtab_chrom[size][1];
97 22016 uni_code ^= (1 << uni_len) - 1; //M$ does not like compatibility
98
99
2/2
✓ Branch 0 taken 21973 times.
✓ Branch 1 taken 43 times.
22016 if (size > 0) {
100 21973 uni_code <<= size; uni_code |= l;
101 21973 uni_len +=size;
102
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 21930 times.
21973 if (size > 8) {
103 43 uni_code <<= 1; uni_code |= 1;
104 43 uni_len++;
105 }
106 }
107 22016 ff_v2_dc_chroma_table[level + 256][0] = uni_code;
108 22016 ff_v2_dc_chroma_table[level + 256][1] = uni_len;
109 }
110 43 }
111
112 43 static av_cold void msmpeg4_common_init_static(void)
113 {
114 static uint8_t rl_table_store[NB_RL_TABLES][2][2 * MAX_RUN + MAX_LEVEL + 3];
115
116
2/2
✓ Branch 0 taken 258 times.
✓ Branch 1 taken 43 times.
301 for (int i = 0; i < NB_RL_TABLES; i++)
117 258 ff_rl_init(&ff_rl_table[i], rl_table_store[i]);
118
119 43 init_h263_dc_for_msmpeg4();
120 43 }
121
122 62 av_cold void ff_msmpeg4_common_init(MPVContext *const s,
123 uint8_t permutated_intra_h_scantable[64],
124 uint8_t permutated_intra_v_scantable[64])
125 {
126 static AVOnce init_static_once = AV_ONCE_INIT;
127
128
4/5
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 13 times.
62 switch(s->msmpeg4_version){
129 default:
130 av_unreachable("ff_msmpeg4_common_init only called by MSMP4 1-3 and WMV1/2");
131 15 case MSMP4_V1:
132 case MSMP4_V2:
133 // Correct *_dc_scale_tables (ff_mpeg1_dc_scale_table) is the default
134 15 break;
135 18 case MSMP4_V3:
136
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 5 times.
18 if(s->workaround_bugs){
137 13 s->y_dc_scale_table= ff_old_ff_y_dc_scale_table;
138 13 s->c_dc_scale_table= ff_wmv1_c_dc_scale_table;
139 } else{
140 5 s->y_dc_scale_table= ff_mpeg4_y_dc_scale_table;
141 5 s->c_dc_scale_table= ff_mpeg4_c_dc_scale_table;
142 }
143 18 break;
144 #if CONFIG_WMV2_DECODER || CONFIG_WMV2_ENCODER
145 16 case MSMP4_WMV2:
146 16 ff_wmv2dsp_init(&s->idsp);
147 av_fallthrough;
148 #endif
149 29 case MSMP4_WMV1:
150 29 s->y_dc_scale_table= ff_wmv1_y_dc_scale_table;
151 29 s->c_dc_scale_table= ff_wmv1_c_dc_scale_table;
152 29 ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_wmv1_scantable[1]);
153 29 ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable, ff_wmv1_scantable[0]);
154 29 ff_permute_scantable(permutated_intra_h_scantable, ff_wmv1_scantable[2],
155 29 s->idsp.idct_permutation);
156 29 ff_permute_scantable(permutated_intra_v_scantable, ff_wmv1_scantable[3],
157 29 s->idsp.idct_permutation);
158 29 break;
159 }
160
161 62 ff_thread_once(&init_static_once, msmpeg4_common_init_static);
162 62 }
163
164 /* predict coded block */
165 168960 int ff_msmpeg4_coded_block_pred(MpegEncContext * s, int n, uint8_t **coded_block_ptr)
166 {
167 int xy, wrap, pred, a, b, c;
168
169 168960 xy = s->block_index[n];
170 168960 wrap = s->b8_stride;
171
172 /* B C
173 * A X
174 */
175 168960 a = s->coded_block[xy - 1 ];
176 168960 b = s->coded_block[xy - 1 - wrap];
177 168960 c = s->coded_block[xy - wrap];
178
179
2/2
✓ Branch 0 taken 150152 times.
✓ Branch 1 taken 18808 times.
168960 if (b == c) {
180 150152 pred = a;
181 } else {
182 18808 pred = c;
183 }
184
185 /* store value */
186 168960 *coded_block_ptr = &s->coded_block[xy];
187
188 168960 return pred;
189 }
190
191 static int get_dc(uint8_t *src, int stride, int scale, int block_size)
192 {
193 int y;
194 int sum=0;
195 for(y=0; y<block_size; y++){
196 int x;
197 for(x=0; x<block_size; x++){
198 sum+=src[x + y*stride];
199 }
200 }
201 return FASTDIV((sum + (scale>>1)), scale);
202 }
203
204 /* dir = 0: left, dir = 1: top prediction */
205 433272 int ff_msmpeg4_pred_dc(MpegEncContext *s, int n,
206 int16_t **dc_val_ptr, int *dir_ptr)
207 {
208 int a, b, c, wrap, pred, scale;
209 433272 int16_t *const dc_val = s->dc_val + s->block_index[n];
210
211 /* find prediction */
212
2/2
✓ Branch 0 taken 288848 times.
✓ Branch 1 taken 144424 times.
433272 if (n < 4) {
213 288848 scale = s->y_dc_scale;
214 } else {
215 144424 scale = s->c_dc_scale;
216 }
217
218 433272 wrap = s->block_wrap[n];
219
220 /* B C
221 * A X
222 */
223 433272 a = dc_val[ - 1];
224 433272 b = dc_val[ - 1 - wrap];
225 433272 c = dc_val[ - wrap];
226
227
6/6
✓ Branch 0 taken 19830 times.
✓ Branch 1 taken 413442 times.
✓ Branch 2 taken 13220 times.
✓ Branch 3 taken 6610 times.
✓ Branch 4 taken 6624 times.
✓ Branch 5 taken 6596 times.
433272 if (s->first_slice_line && !(n & 2) && s->msmpeg4_version < MSMP4_WMV1)
228 6624 b=c=1024;
229
230 /* XXX: the following solution consumes divisions, but it does not
231 necessitate to modify mpegvideo.c. The problem comes from the
232 fact they decided to store the quantized DC (which would lead
233 to problems if Q could vary !) */
234 #if ARCH_X86 && HAVE_7REGS && HAVE_EBX_AVAILABLE
235 433272 __asm__ volatile(
236 "movl %3, %%eax \n\t"
237 "shrl $1, %%eax \n\t"
238 "addl %%eax, %2 \n\t"
239 "addl %%eax, %1 \n\t"
240 "addl %0, %%eax \n\t"
241 "imull %4 \n\t"
242 "movl %%edx, %0 \n\t"
243 "movl %1, %%eax \n\t"
244 "imull %4 \n\t"
245 "movl %%edx, %1 \n\t"
246 "movl %2, %%eax \n\t"
247 "imull %4 \n\t"
248 "movl %%edx, %2 \n\t"
249 : "+b" (a), "+c" (b), "+D" (c)
250 433272 : "g" (scale), "S" (ff_inverse[scale])
251 : "%eax", "%edx"
252 );
253 #else
254 /* Divisions are costly everywhere; optimize the most common case. */
255 if (scale == 8) {
256 a = (a + (8 >> 1)) / 8;
257 b = (b + (8 >> 1)) / 8;
258 c = (c + (8 >> 1)) / 8;
259 } else {
260 a = FASTDIV((a + (scale >> 1)), scale);
261 b = FASTDIV((b + (scale >> 1)), scale);
262 c = FASTDIV((c + (scale >> 1)), scale);
263 }
264 #endif
265 /* XXX: WARNING: they did not choose the same test as MPEG-4. This
266 is very important ! */
267
2/2
✓ Branch 0 taken 212484 times.
✓ Branch 1 taken 220788 times.
433272 if (s->msmpeg4_version > MSMP4_V3) {
268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 212484 times.
212484 if(s->inter_intra_pred){
269 uint8_t *dest;
270 int wrap;
271
272 if(n==1){
273 pred=a;
274 *dir_ptr = 0;
275 }else if(n==2){
276 pred=c;
277 *dir_ptr = 1;
278 }else if(n==3){
279 if (abs(a - b) < abs(b - c)) {
280 pred = c;
281 *dir_ptr = 1;
282 } else {
283 pred = a;
284 *dir_ptr = 0;
285 }
286 }else{
287 int bs = 8 >> s->avctx->lowres;
288 if(n<4){
289 wrap= s->linesize;
290 dest = s->cur_pic.data[0] + (((n >> 1) + 2*s->mb_y) * bs* wrap ) + ((n & 1) + 2*s->mb_x) * bs;
291 }else{
292 wrap= s->uvlinesize;
293 dest = s->cur_pic.data[n - 3] + (s->mb_y * bs * wrap) + s->mb_x * bs;
294 }
295 if(s->mb_x==0) a= (1024 + (scale>>1))/scale;
296 else a= get_dc(dest-bs, wrap, scale*8>>(2*s->avctx->lowres), bs);
297 if(s->mb_y==0) c= (1024 + (scale>>1))/scale;
298 else c= get_dc(dest-bs*wrap, wrap, scale*8>>(2*s->avctx->lowres), bs);
299
300 if (s->h263_aic_dir==0) {
301 pred= a;
302 *dir_ptr = 0;
303 }else if (s->h263_aic_dir==1) {
304 if(n==0){
305 pred= c;
306 *dir_ptr = 1;
307 }else{
308 pred= a;
309 *dir_ptr = 0;
310 }
311 }else if (s->h263_aic_dir==2) {
312 if(n==0){
313 pred= a;
314 *dir_ptr = 0;
315 }else{
316 pred= c;
317 *dir_ptr = 1;
318 }
319 } else {
320 pred= c;
321 *dir_ptr = 1;
322 }
323 }
324 }else{
325
2/2
✓ Branch 0 taken 86305 times.
✓ Branch 1 taken 126179 times.
212484 if (abs(a - b) < abs(b - c)) {
326 86305 pred = c;
327 86305 *dir_ptr = 1;
328 } else {
329 126179 pred = a;
330 126179 *dir_ptr = 0;
331 }
332 }
333 }else{
334
2/2
✓ Branch 0 taken 116422 times.
✓ Branch 1 taken 104366 times.
220788 if (abs(a - b) <= abs(b - c)) {
335 116422 pred = c;
336 116422 *dir_ptr = 1;
337 } else {
338 104366 pred = a;
339 104366 *dir_ptr = 0;
340 }
341 }
342
343 /* update predictor */
344 433272 *dc_val_ptr = &dc_val[0];
345 433272 return pred;
346 }
347