FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/ac3dsp.c
Date: 2026-09-17 06:33:28
Exec Total Coverage
Lines: 216 223 96.9%
Functions: 17 17 100.0%
Branches: 89 106 84.0%

Line Branch Exec Source
1 /*
2 * AC-3 DSP functions
3 * Copyright (c) 2011 Justin Ruggles
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include <math.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "config.h"
27 #include "libavutil/attributes.h"
28 #include "libavutil/common.h"
29 #include "libavutil/intmath.h"
30 #include "libavutil/mem_internal.h"
31
32 #include "ac3defs.h"
33 #include "ac3dsp.h"
34 #include "ac3tab.h"
35 #include "mathops.h"
36
37 4092 static void ac3_exponent_min_c(uint8_t *exp, int num_reuse_blocks, int nb_coefs)
38 {
39 int blk, i;
40
41
2/2
✓ Branch 0 taken 798 times.
✓ Branch 1 taken 3294 times.
4092 if (!num_reuse_blocks)
42 798 return;
43
44
2/2
✓ Branch 0 taken 843264 times.
✓ Branch 1 taken 3294 times.
846558 for (i = 0; i < nb_coefs; i++) {
45 843264 uint8_t min_exp = *exp;
46 843264 uint8_t *exp1 = exp + 256;
47
2/2
✓ Branch 0 taken 3554304 times.
✓ Branch 1 taken 843264 times.
4397568 for (blk = 0; blk < num_reuse_blocks; blk++) {
48 3554304 uint8_t next_exp = *exp1;
49
2/2
✓ Branch 0 taken 522749 times.
✓ Branch 1 taken 3031555 times.
3554304 if (next_exp < min_exp)
50 522749 min_exp = next_exp;
51 3554304 exp1 += 256;
52 }
53 843264 *exp++ = min_exp;
54 }
55 }
56
57 4274 static void float_to_fixed24_c(int32_t *dst, const float *src, size_t len)
58 {
59 4274 const float scale = 1 << 24;
60 do {
61 366512 *dst++ = lrintf(*src++ * scale);
62 366512 *dst++ = lrintf(*src++ * scale);
63 366512 *dst++ = lrintf(*src++ * scale);
64 366512 *dst++ = lrintf(*src++ * scale);
65 366512 *dst++ = lrintf(*src++ * scale);
66 366512 *dst++ = lrintf(*src++ * scale);
67 366512 *dst++ = lrintf(*src++ * scale);
68 366512 *dst++ = lrintf(*src++ * scale);
69 366512 len -= 8;
70
2/2
✓ Branch 0 taken 362238 times.
✓ Branch 1 taken 4274 times.
366512 } while (len > 0);
71 4274 }
72
73 229497 static void ac3_bit_alloc_calc_bap_c(int16_t *mask, int16_t *psd,
74 int start, int end,
75 int snr_offset, int floor,
76 const uint8_t *bap_tab, uint8_t *bap)
77 {
78 int bin, band, band_end;
79
80 /* special case, if snr offset is -960, set all bap's to zero */
81
2/2
✓ Branch 0 taken 34208 times.
✓ Branch 1 taken 195289 times.
229497 if (snr_offset == -960) {
82 34208 memset(bap, 0, AC3_MAX_COEFS);
83 34208 return;
84 }
85
86 /* the first 28 bands have one coefficient each */
87
2/2
✓ Branch 0 taken 1573845 times.
✓ Branch 1 taken 195289 times.
1769134 for (bin = start; bin < FFMIN(end, 28); bin++) {
88 1573845 int m = (FFMAX(mask[bin] - snr_offset - floor, 0) & 0x1FE0) + floor;
89 1573845 int address = av_clip_uintp2((psd[bin] - m) >> 5, 6);
90 1573845 bap[bin] = bap_tab[address];
91 }
92
2/2
✓ Branch 0 taken 12667 times.
✓ Branch 1 taken 182622 times.
195289 if (bin >= end)
93 12667 return;
94
95 182622 band = ff_ac3_bin_to_band_tab[bin];
96 do {
97 1564257 int m = (FFMAX(mask[band] - snr_offset - floor, 0) & 0x1FE0) + floor;
98 1564257 band_end = ff_ac3_band_start_tab[++band];
99 1564257 band_end = FFMIN(band_end, end);
100
101
2/2
✓ Branch 0 taken 15015904 times.
✓ Branch 1 taken 1564257 times.
16580161 for (; bin < band_end; bin++) {
102 15015904 int address = av_clip_uintp2((psd[bin] - m) >> 5, 6);
103 15015904 bap[bin] = bap_tab[address];
104 }
105
2/2
✓ Branch 0 taken 1381635 times.
✓ Branch 1 taken 182622 times.
1564257 } while (end > band_end);
106 }
107
108 38096 static void ac3_update_bap_counts_c(uint16_t mant_cnt[16], const uint8_t bap[],
109 int len)
110 {
111
2/2
✓ Branch 0 taken 4346075 times.
✓ Branch 1 taken 38096 times.
4384171 while (len-- > 0)
112 4346075 mant_cnt[bap[len]]++;
113 38096 }
114
115 DECLARE_ALIGNED(16, const uint16_t, ff_ac3_bap_bits)[16] = {
116 0, 0, 0, 3, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16
117 };
118
119 10420 static int ac3_compute_mantissa_size_c(const uint16_t mant_cnt[6][16])
120 {
121 int blk, bap;
122 10420 int bits = 0;
123
124
2/2
✓ Branch 0 taken 62520 times.
✓ Branch 1 taken 10420 times.
72940 for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
125 // bap=1 : 3 mantissas in 5 bits
126 62520 bits += (mant_cnt[blk][1] / 3) * 5;
127 // bap=2 : 3 mantissas in 7 bits
128 // bap=4 : 2 mantissas in 7 bits
129 62520 bits += ((mant_cnt[blk][2] / 3) + (mant_cnt[blk][4] >> 1)) * 7;
130 // bap=3 : 1 mantissa in 3 bits
131 62520 bits += mant_cnt[blk][3] * 3;
132 // bap=5 to 15 : get bits per mantissa from table
133
2/2
✓ Branch 0 taken 687720 times.
✓ Branch 1 taken 62520 times.
750240 for (bap = 5; bap < 16; bap++)
134 687720 bits += mant_cnt[blk][bap] * ff_ac3_bap_bits[bap];
135 }
136 10420 return bits;
137 }
138
139 6286 static void ac3_extract_exponents_c(uint8_t *exp, const int32_t *coef, int nb_coefs)
140 {
141 int i;
142
143
2/2
✓ Branch 0 taken 4824320 times.
✓ Branch 1 taken 6286 times.
4830606 for (i = 0; i < nb_coefs; i++) {
144 4824320 int v = abs(coef[i]);
145
2/2
✓ Branch 0 taken 3523522 times.
✓ Branch 1 taken 1300798 times.
4824320 exp[i] = v ? 23 - av_log2(v) : 24;
146 }
147 6286 }
148
149 12675 static void ac3_sum_square_butterfly_int32_c(int64_t sum[4],
150 const int32_t *coef0,
151 const int32_t *coef1,
152 int len)
153 {
154 int i;
155
156 12675 sum[0] = sum[1] = sum[2] = sum[3] = 0;
157
158
2/2
✓ Branch 0 taken 352620 times.
✓ Branch 1 taken 12675 times.
365295 for (i = 0; i < len; i++) {
159 352620 int lt = coef0[i];
160 352620 int rt = coef1[i];
161 352620 int md = lt + rt;
162 352620 int sd = lt - rt;
163 352620 MAC64(sum[0], lt, lt);
164 352620 MAC64(sum[1], rt, rt);
165 352620 MAC64(sum[2], md, md);
166 352620 MAC64(sum[3], sd, sd);
167 }
168 12675 }
169
170 33711 static void ac3_sum_square_butterfly_float_c(float sum[4],
171 const float *coef0,
172 const float *coef1,
173 int len)
174 {
175 int i;
176
177 33711 sum[0] = sum[1] = sum[2] = sum[3] = 0;
178
179
2/2
✓ Branch 0 taken 859740 times.
✓ Branch 1 taken 33711 times.
893451 for (i = 0; i < len; i++) {
180 859740 float lt = coef0[i];
181 859740 float rt = coef1[i];
182 859740 float md = lt + rt;
183 859740 float sd = lt - rt;
184 859740 sum[0] += lt * lt;
185 859740 sum[1] += rt * rt;
186 859740 sum[2] += md * md;
187 859740 sum[3] += sd * sd;
188 }
189 33711 }
190
191 342 static void ac3_downmix_5_to_2_symmetric_c(float **samples, float **matrix,
192 int len)
193 {
194 int i;
195 float v0, v1;
196 342 float front_mix = matrix[0][0];
197 342 float center_mix = matrix[0][1];
198 342 float surround_mix = matrix[0][3];
199
200
2/2
✓ Branch 0 taken 87552 times.
✓ Branch 1 taken 342 times.
87894 for (i = 0; i < len; i++) {
201 87552 v0 = samples[0][i] * front_mix +
202 87552 samples[1][i] * center_mix +
203 87552 samples[3][i] * surround_mix;
204
205 87552 v1 = samples[1][i] * center_mix +
206 87552 samples[2][i] * front_mix +
207 87552 samples[4][i] * surround_mix;
208
209 87552 samples[0][i] = v0;
210 87552 samples[1][i] = v1;
211 }
212 342 }
213
214 342 static void ac3_downmix_5_to_1_symmetric_c(float **samples, float **matrix,
215 int len)
216 {
217 int i;
218 342 float front_mix = matrix[0][0];
219 342 float center_mix = matrix[0][1];
220 342 float surround_mix = matrix[0][3];
221
222
2/2
✓ Branch 0 taken 87552 times.
✓ Branch 1 taken 342 times.
87894 for (i = 0; i < len; i++) {
223 87552 samples[0][i] = samples[0][i] * front_mix +
224 87552 samples[1][i] * center_mix +
225 87552 samples[2][i] * front_mix +
226 87552 samples[3][i] * surround_mix +
227 87552 samples[4][i] * surround_mix;
228 }
229 342 }
230
231 764 static void ac3_downmix_c(float **samples, float **matrix,
232 int out_ch, int in_ch, int len)
233 {
234 int i, j;
235 float v0, v1;
236
237
2/2
✓ Branch 0 taken 379 times.
✓ Branch 1 taken 385 times.
764 if (out_ch == 2) {
238
2/2
✓ Branch 0 taken 96896 times.
✓ Branch 1 taken 379 times.
97275 for (i = 0; i < len; i++) {
239 96896 v0 = v1 = 0.0f;
240
2/2
✓ Branch 0 taken 387584 times.
✓ Branch 1 taken 96896 times.
484480 for (j = 0; j < in_ch; j++) {
241 387584 v0 += samples[j][i] * matrix[0][j];
242 387584 v1 += samples[j][i] * matrix[1][j];
243 }
244 96896 samples[0][i] = v0;
245 96896 samples[1][i] = v1;
246 }
247
1/2
✓ Branch 0 taken 385 times.
✗ Branch 1 not taken.
385 } else if (out_ch == 1) {
248
2/2
✓ Branch 0 taken 98432 times.
✓ Branch 1 taken 385 times.
98817 for (i = 0; i < len; i++) {
249 98432 v0 = 0.0f;
250
2/2
✓ Branch 0 taken 393728 times.
✓ Branch 1 taken 98432 times.
492160 for (j = 0; j < in_ch; j++)
251 393728 v0 += samples[j][i] * matrix[0][j];
252 98432 samples[0][i] = v0;
253 }
254 }
255 764 }
256
257 330 static void ac3_downmix_5_to_2_symmetric_c_fixed(int32_t **samples, int16_t **matrix,
258 int len)
259 {
260 int i;
261 int64_t v0, v1;
262 330 int16_t front_mix = matrix[0][0];
263 330 int16_t center_mix = matrix[0][1];
264 330 int16_t surround_mix = matrix[0][3];
265
266
2/2
✓ Branch 0 taken 84480 times.
✓ Branch 1 taken 330 times.
84810 for (i = 0; i < len; i++) {
267 84480 v0 = (int64_t)samples[0][i] * front_mix +
268 84480 (int64_t)samples[1][i] * center_mix +
269 84480 (int64_t)samples[3][i] * surround_mix;
270
271 84480 v1 = (int64_t)samples[1][i] * center_mix +
272 84480 (int64_t)samples[2][i] * front_mix +
273 84480 (int64_t)samples[4][i] * surround_mix;
274
275 84480 samples[0][i] = (v0+2048)>>12;
276 84480 samples[1][i] = (v1+2048)>>12;
277 }
278 330 }
279
280 330 static void ac3_downmix_5_to_1_symmetric_c_fixed(int32_t **samples, int16_t **matrix,
281 int len)
282 {
283 int i;
284 int64_t v0;
285 330 int16_t front_mix = matrix[0][0];
286 330 int16_t center_mix = matrix[0][1];
287 330 int16_t surround_mix = matrix[0][3];
288
289
2/2
✓ Branch 0 taken 84480 times.
✓ Branch 1 taken 330 times.
84810 for (i = 0; i < len; i++) {
290 84480 v0 = (int64_t)samples[0][i] * front_mix +
291 84480 (int64_t)samples[1][i] * center_mix +
292 84480 (int64_t)samples[2][i] * front_mix +
293 84480 (int64_t)samples[3][i] * surround_mix +
294 84480 (int64_t)samples[4][i] * surround_mix;
295
296 84480 samples[0][i] = (v0+2048)>>12;
297 }
298 330 }
299
300 372 static void ac3_downmix_c_fixed(int32_t **samples, int16_t **matrix,
301 int out_ch, int in_ch, int len)
302 {
303 int i, j;
304 int64_t v0, v1;
305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 372 times.
372 if (out_ch == 2) {
306 for (i = 0; i < len; i++) {
307 v0 = v1 = 0;
308 for (j = 0; j < in_ch; j++) {
309 v0 += (int64_t)samples[j][i] * matrix[0][j];
310 v1 += (int64_t)samples[j][i] * matrix[1][j];
311 }
312 samples[0][i] = (v0+2048)>>12;
313 samples[1][i] = (v1+2048)>>12;
314 }
315
1/2
✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
372 } else if (out_ch == 1) {
316
2/2
✓ Branch 0 taken 95104 times.
✓ Branch 1 taken 372 times.
95476 for (i = 0; i < len; i++) {
317 95104 v0 = 0;
318
2/2
✓ Branch 0 taken 380416 times.
✓ Branch 1 taken 95104 times.
475520 for (j = 0; j < in_ch; j++)
319 380416 v0 += (int64_t)samples[j][i] * matrix[0][j];
320 95104 samples[0][i] = (v0+2048)>>12;
321 }
322 }
323 372 }
324
325 1032 void ff_ac3dsp_downmix_fixed(AC3DSPContext *c, int32_t **samples, int16_t **matrix,
326 int out_ch, int in_ch, int len)
327 {
328
3/4
✓ Branch 0 taken 1029 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1029 times.
1032 if (c->in_channels != in_ch || c->out_channels != out_ch) {
329 3 c->in_channels = in_ch;
330 3 c->out_channels = out_ch;
331 3 c->downmix_fixed = NULL;
332
333
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
3 if (in_ch == 5 && out_ch == 2 &&
334 1 !(matrix[1][0] | matrix[0][2] |
335 1 matrix[1][3] | matrix[0][4] |
336 1 (matrix[0][1] ^ matrix[1][1]) |
337
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 (matrix[0][0] ^ matrix[1][2]))) {
338 1 c->downmix_fixed = ac3_downmix_5_to_2_symmetric_c_fixed;
339
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 } else if (in_ch == 5 && out_ch == 1 &&
340
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 matrix[0][0] == matrix[0][2] &&
341
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 matrix[0][3] == matrix[0][4]) {
342 1 c->downmix_fixed = ac3_downmix_5_to_1_symmetric_c_fixed;
343 }
344 }
345
346
2/2
✓ Branch 0 taken 660 times.
✓ Branch 1 taken 372 times.
1032 if (c->downmix_fixed)
347 660 c->downmix_fixed(samples, matrix, len);
348 else
349 372 ac3_downmix_c_fixed(samples, matrix, out_ch, in_ch, len);
350 1032 }
351
352 1448 void ff_ac3dsp_downmix(AC3DSPContext *c, float **samples, float **matrix,
353 int out_ch, int in_ch, int len)
354 {
355
3/4
✓ Branch 0 taken 1437 times.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1437 times.
1448 if (c->in_channels != in_ch || c->out_channels != out_ch) {
356 11 int **matrix_cmp = (int **)matrix;
357
358 11 c->in_channels = in_ch;
359 11 c->out_channels = out_ch;
360 11 c->downmix = NULL;
361
362
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
11 if (in_ch == 5 && out_ch == 2 &&
363 3 !(matrix_cmp[1][0] | matrix_cmp[0][2] |
364 3 matrix_cmp[1][3] | matrix_cmp[0][4] |
365 3 (matrix_cmp[0][1] ^ matrix_cmp[1][1]) |
366
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 (matrix_cmp[0][0] ^ matrix_cmp[1][2]))) {
367 3 c->downmix = ac3_downmix_5_to_2_symmetric_c;
368
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
8 } else if (in_ch == 5 && out_ch == 1 &&
369
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 matrix_cmp[0][0] == matrix_cmp[0][2] &&
370
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 matrix_cmp[0][3] == matrix_cmp[0][4]) {
371 3 c->downmix = ac3_downmix_5_to_1_symmetric_c;
372 }
373
374 #if ARCH_X86 && HAVE_X86ASM
375 11 ff_ac3dsp_set_downmix_x86(c);
376 #endif
377 }
378
379
2/2
✓ Branch 0 taken 684 times.
✓ Branch 1 taken 764 times.
1448 if (c->downmix)
380 684 c->downmix(samples, matrix, len);
381 else
382 764 ac3_downmix_c(samples, matrix, out_ch, in_ch, len);
383 1448 }
384
385 151 av_cold void ff_ac3dsp_init(AC3DSPContext *c)
386 {
387 151 c->ac3_exponent_min = ac3_exponent_min_c;
388 151 c->float_to_fixed24 = float_to_fixed24_c;
389 151 c->bit_alloc_calc_bap = ac3_bit_alloc_calc_bap_c;
390 151 c->update_bap_counts = ac3_update_bap_counts_c;
391 151 c->compute_mantissa_size = ac3_compute_mantissa_size_c;
392 151 c->extract_exponents = ac3_extract_exponents_c;
393 151 c->sum_square_butterfly_int32 = ac3_sum_square_butterfly_int32_c;
394 151 c->sum_square_butterfly_float = ac3_sum_square_butterfly_float_c;
395 151 c->in_channels = 0;
396 151 c->out_channels = 0;
397 151 c->downmix = NULL;
398 151 c->downmix_fixed = NULL;
399
400 #if ARCH_AARCH64
401 ff_ac3dsp_init_aarch64(c);
402 #elif ARCH_ARM
403 ff_ac3dsp_init_arm(c);
404 #elif ARCH_X86 && HAVE_X86ASM
405 151 ff_ac3dsp_init_x86(c);
406 #elif ARCH_MIPS
407 ff_ac3dsp_init_mips(c);
408 #elif ARCH_RISCV
409 ff_ac3dsp_init_riscv(c);
410 #endif
411 151 }
412