FFmpeg coverage


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