FFmpeg coverage


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