FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libswresample/tests/rematrix.c
Date: 2026-09-04 22:37:26
Exec Total Coverage
Lines: 54 72 75.0%
Functions: 4 4 100.0%
Branches: 34 46 73.9%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2026 Ayoub Nabil Boubagrat
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <limits.h>
22 #include <stdio.h>
23
24 #include "libavutil/channel_layout.h"
25 #include "libavutil/mathematics.h"
26 #include "libswresample/swresample.h"
27
28 /* swr_build_matrix2() accesses an internal SWR_CH_MAX by SWR_CH_MAX matrix. */
29 #define MATRIX_STRIDE 64
30
31 27008 static int channel_is_unused(const AVChannelLayout *layout, int index)
32 {
33 27008 return av_channel_layout_channel_from_index(layout, index) == AV_CHAN_UNUSED;
34 }
35
36 449 static void print_matrix_row(const double *matrix,
37 const AVChannelLayout *in_layout,
38 int out, const char *out_name)
39 {
40 char in_name[16];
41
42 449 printf("[%s] = { ", out_name);
43
2/2
✓ Branch 0 taken 28736 times.
✓ Branch 1 taken 449 times.
29185 for (int i = 0; i < 64; i++) {
44 28736 enum AVChannel in_ch = av_channel_layout_channel_from_index(in_layout, i);
45
2/2
✓ Branch 0 taken 21982 times.
✓ Branch 1 taken 6754 times.
28736 if (in_ch == AV_CHAN_NONE)
46 21982 continue;
47 6754 av_channel_name(in_name, sizeof(in_name), in_ch);
48
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6750 times.
6754 if (in_ch == AV_CHAN_UNUSED)
49 4 printf(".UNSD%d = %f, ", i,
50 4 matrix[out * MATRIX_STRIDE + i]);
51 else
52 6750 printf(".%s = %f, ", in_name, matrix[out * MATRIX_STRIDE + i]);
53 }
54 449 printf("},\n");
55 449 }
56
57 68 static int print_matrix(const AVChannelLayout *in_layout,
58 const AVChannelLayout *out_layout)
59 {
60 68 double matrix[MATRIX_STRIDE * MATRIX_STRIDE] = { 0 };
61 char out_name[16];
62 int ret;
63
64 /* ensure swr_build_matrix2() overwrites unused columns and rows with zero. */
65
2/2
✓ Branch 0 taken 449 times.
✓ Branch 1 taken 68 times.
517 for (int out = 0; out < out_layout->nb_channels; out++)
66
2/2
✓ Branch 0 taken 6754 times.
✓ Branch 1 taken 449 times.
7203 for (int in = 0; in < in_layout->nb_channels; in++)
67
4/4
✓ Branch 1 taken 6750 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 6738 times.
13504 if (channel_is_unused(in_layout, in) ||
68 6750 channel_is_unused(out_layout, out))
69 16 matrix[out * MATRIX_STRIDE + in] = 1.0;
70
71 /* Disable normalization so the raw downmix gains can be checked. */
72 68 ret = swr_build_matrix2(in_layout, out_layout, M_SQRT1_2,
73 M_SQRT1_2,
74 0.0, INT_MAX, 1.0, matrix, MATRIX_STRIDE,
75 AV_MATRIX_ENCODING_NONE, NULL);
76
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (ret < 0) {
77 fprintf(stderr, "swr_build_matrix2 failed with error %d\n", ret);
78 return 1;
79 }
80
81
2/2
✓ Branch 0 taken 449 times.
✓ Branch 1 taken 68 times.
517 for (int out = 0; out < out_layout->nb_channels; out++) {
82
2/2
✓ Branch 0 taken 6754 times.
✓ Branch 1 taken 449 times.
7203 for (int in = 0; in < in_layout->nb_channels; in++) {
83
4/4
✓ Branch 1 taken 6750 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 6738 times.
13504 if ((channel_is_unused(in_layout, in) ||
84 6750 channel_is_unused(out_layout, out)) &&
85
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 matrix[out * MATRIX_STRIDE + in] != 0.0) {
86 fprintf(stderr, "unused matrix position %d:%d is non-zero\n",
87 out, in);
88 return 1;
89 }
90 }
91 }
92
93
2/2
✓ Branch 0 taken 449 times.
✓ Branch 1 taken 68 times.
517 for (int i = 0; i < out_layout->nb_channels; i++) {
94 449 enum AVChannel out_ch = av_channel_layout_channel_from_index(out_layout, i);
95
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 449 times.
449 if (out_ch == AV_CHAN_NONE)
96 continue;
97
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 447 times.
449 if (out_ch == AV_CHAN_UNUSED)
98 2 snprintf(out_name, sizeof(out_name), "UNSD%d", i);
99 else
100 447 av_channel_name(out_name, sizeof(out_name), out_ch);
101 449 print_matrix_row(matrix, in_layout, i, out_name);
102 }
103
104 68 return 0;
105 }
106
107 68 int main(int argc, char **argv)
108 {
109 68 AVChannelLayout in_layout = { 0 }, out_layout = { 0 };
110 const char *in, *out;
111 68 int ret = 0;
112
113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (argc != 3) {
114 printf("usage: rematrix input_layout output_layout\n");
115 return 0;
116 }
117
118 68 in = argv[1];
119 68 out = argv[2];
120
121 68 ret = av_channel_layout_from_string(&in_layout, in);
122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (ret < 0) {
123 if (ret == AVERROR(EINVAL))
124 fprintf(stderr, "Invalid input layout %s\n", in);
125 ret = 1;
126 goto end;
127 }
128
129 68 ret = av_channel_layout_from_string(&out_layout, out);
130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (ret < 0) {
131 if (ret == AVERROR(EINVAL))
132 fprintf(stderr, "Invalid output layout %s\n", out);
133 ret = 1;
134 goto end;
135 }
136
137
1/2
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
68 if (in_layout.nb_channels > MATRIX_STRIDE ||
138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 out_layout.nb_channels > MATRIX_STRIDE) {
139 fprintf(stderr, "channel layout exceeds matrix capacity\n");
140 ret = 1;
141 goto end;
142 }
143
144 68 ret = print_matrix(&in_layout, &out_layout);
145
146 68 end:
147 68 av_channel_layout_uninit(&in_layout);
148 68 av_channel_layout_uninit(&out_layout);
149
150 68 return ret;
151 }
152