FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/msmpeg4.c
Date: 2026-08-11 17:55:23
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 43 static av_cold void init_h263_dc_for_msmpeg4(void)
58 {
59
2/2
✓ Branch 0 taken 22016 times.
✓ Branch 1 taken 43 times.
22059 for (int level = -256; level < 256; level++) {
60 int uni_code, uni_len;
61 int size, v, l;
62 /* find number of bits */
63 22016 size = 0;
64 22016 v = abs(level);
65
2/2
✓ Branch 0 taken 154585 times.
✓ Branch 1 taken 22016 times.
176601 while (v) {
66 154585 v >>= 1;
67 154585 size++;
68 }
69
70
2/2
✓ Branch 0 taken 11008 times.
✓ Branch 1 taken 11008 times.
22016 if (level < 0)
71 11008 l = (-level) ^ ((1 << size) - 1);
72 else
73 11008 l = level;
74
75 /* luminance H.263 */
76 22016 uni_code = ff_mpeg4_DCtab_lum[size][0];
77 22016 uni_len = ff_mpeg4_DCtab_lum[size][1];
78 22016 uni_code ^= (1 << uni_len) - 1; //M$ does not like compatibility
79
80
2/2
✓ Branch 0 taken 21973 times.
✓ Branch 1 taken 43 times.
22016 if (size > 0) {
81 21973 uni_code <<= size; uni_code |= l;
82 21973 uni_len += size;
83
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 21930 times.
21973 if (size > 8) {
84 43 uni_code <<= 1; uni_code |= 1;
85 43 uni_len++;
86 }
87 }
88 22016 ff_v2_dc_lum_table[level + 256][0] = uni_code;
89 22016 ff_v2_dc_lum_table[level + 256][1] = uni_len;
90
91 /* chrominance H.263 */
92 22016 uni_code = ff_mpeg4_DCtab_chrom[size][0];
93 22016 uni_len = ff_mpeg4_DCtab_chrom[size][1];
94 22016 uni_code ^= (1 << uni_len) - 1; //M$ does not like compatibility
95
96
2/2
✓ Branch 0 taken 21973 times.
✓ Branch 1 taken 43 times.
22016 if (size > 0) {
97 21973 uni_code <<= size; uni_code |= l;
98 21973 uni_len +=size;
99
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 21930 times.
21973 if (size > 8) {
100 43 uni_code <<= 1; uni_code |= 1;
101 43 uni_len++;
102 }
103 }
104 22016 ff_v2_dc_chroma_table[level + 256][0] = uni_code;
105 22016 ff_v2_dc_chroma_table[level + 256][1] = uni_len;
106 }
107 43 }
108
109 43 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 258 times.
✓ Branch 1 taken 43 times.
301 for (int i = 0; i < NB_RL_TABLES; i++)
114 258 ff_rl_init(&ff_rl_table[i], rl_table_store[i]);
115
116 43 init_h263_dc_for_msmpeg4();
117 43 }
118
119 62 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 16 times.
✓ Branch 4 taken 13 times.
62 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 16 case MSMP4_WMV2:
143 16 ff_wmv2dsp_init(&s->idsp);
144 av_fallthrough;
145 #endif
146 29 case MSMP4_WMV1:
147 29 s->y_dc_scale_table= ff_wmv1_y_dc_scale_table;
148 29 s->c_dc_scale_table= ff_wmv1_c_dc_scale_table;
149 29 ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_wmv1_scantable[1]);
150 29 ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable, ff_wmv1_scantable[0]);
151 29 ff_permute_scantable(permutated_intra_h_scantable, ff_wmv1_scantable[2],
152 29 s->idsp.idct_permutation);
153 29 ff_permute_scantable(permutated_intra_v_scantable, ff_wmv1_scantable[3],
154 29 s->idsp.idct_permutation);
155 29 break;
156 }
157
158 62 ff_thread_once(&init_static_once, msmpeg4_common_init_static);
159 62 }
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