FFmpeg
rematrix.c
Go to the documentation of this file.
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 
25 #include "libavutil/mathematics.h"
27 
28 /* swr_build_matrix2() accesses an internal SWR_CH_MAX by SWR_CH_MAX matrix. */
29 #define MATRIX_STRIDE 64
30 
31 static int check_coefficient_with_slev(const AVChannelLayout *in_layout,
32  const AVChannelLayout *out_layout,
33  enum AVChannel in_channel,
34  enum AVChannel out_channel,
35  double surround_mix_level,
36  double expected)
37 {
38  double matrix[MATRIX_STRIDE * MATRIX_STRIDE] = { 0 };
39  char in_name[16], out_name[16];
40  int in, out, ret;
41 
42  av_channel_name(in_name, sizeof(in_name), in_channel);
43  av_channel_name(out_name, sizeof(out_name), out_channel);
44 
45  if (in_layout->nb_channels > MATRIX_STRIDE ||
46  out_layout->nb_channels > MATRIX_STRIDE) {
47  fprintf(stderr, "channel layout exceeds matrix capacity\n");
48  return 1;
49  }
50 
51  in = av_channel_layout_index_from_channel(in_layout, in_channel);
52  out = av_channel_layout_index_from_channel(out_layout, out_channel);
53  if (in < 0) {
54  fprintf(stderr, "input channel %s is not in the input layout\n", in_name);
55  return 1;
56  }
57  if (out < 0) {
58  fprintf(stderr, "output channel %s is not in the output layout\n", out_name);
59  return 1;
60  }
61 
62  /* Disable normalization so the raw downmix gains can be checked. */
63  ret = swr_build_matrix2(in_layout, out_layout, M_SQRT1_2,
64  surround_mix_level,
65  0.0, INT_MAX, 1.0, matrix, MATRIX_STRIDE,
67  if (ret < 0) {
68  fprintf(stderr, "swr_build_matrix2 failed with error %d\n", ret);
69  return 1;
70  }
71 
72  if (fabs(matrix[out * MATRIX_STRIDE + in] - expected) > 1e-12) {
73  fprintf(stderr, "%s -> %s: expected %.12f, got %.12f\n",
74  in_name, out_name, expected,
75  matrix[out * MATRIX_STRIDE + in]);
76  return 1;
77  }
78 
79  return 0;
80 }
81 
82 static int check_coefficient(const AVChannelLayout *in_layout,
83  const AVChannelLayout *out_layout,
84  enum AVChannel in_channel,
85  enum AVChannel out_channel, double expected)
86 {
87  return check_coefficient_with_slev(in_layout, out_layout, in_channel,
88  out_channel, M_SQRT1_2, expected);
89 }
90 
91 int main(void)
92 {
96  const AVChannelLayout surround_back = AV_CHANNEL_LAYOUT_5POINT1_BACK;
100  int ret = 0;
101 
102  ret |= check_coefficient(&surround_2, &stereo,
104  ret |= check_coefficient(&surround_2, &stereo,
106  ret |= check_coefficient(&surround_4, &surround_2,
108  M_SQRT1_2);
109  ret |= check_coefficient(&surround_4, &surround_2,
111  M_SQRT1_2);
112  ret |= check_coefficient(&surround_4, &surround_tbc,
114  M_SQRT1_2);
115  ret |= check_coefficient(&surround_4, &surround_tbc,
117  M_SQRT1_2);
118  ret |= check_coefficient(&surround_4, &surround,
120  ret |= check_coefficient(&surround_4, &surround,
122  ret |= check_coefficient(&surround_4, &surround_back,
124  ret |= check_coefficient(&surround_4, &surround_back,
126  ret |= check_coefficient(&surround_4, &stereo,
128  M_SQRT1_2);
129  ret |= check_coefficient(&surround_4, &stereo,
131  M_SQRT1_2);
132  ret |= check_coefficient_with_slev(&surround_4, &stereo,
134  AV_CHAN_FRONT_LEFT, 0.5, 0.5);
135  ret |= check_coefficient_with_slev(&surround_4, &stereo,
137  AV_CHAN_FRONT_RIGHT, 0.5, 0.5);
138  ret |= check_coefficient(&surround_4, &mono,
140  M_SQRT1_2);
141  ret |= check_coefficient(&surround_4, &mono,
143  M_SQRT1_2);
144  ret |= check_coefficient(&surround_tbc, &surround,
146  M_SQRT1_2);
147  ret |= check_coefficient(&surround_tbc, &surround,
149  M_SQRT1_2);
150  ret |= check_coefficient(&surround_tbc, &surround_4,
152  M_SQRT1_2);
153  ret |= check_coefficient(&surround_tbc, &surround_4,
155  M_SQRT1_2);
156  ret |= check_coefficient(&surround_tbc, &surround_back,
158  M_SQRT1_2);
159  ret |= check_coefficient(&surround_tbc, &surround_back,
161  M_SQRT1_2);
162  ret |= check_coefficient(&surround_tbc, &stereo,
164  ret |= check_coefficient(&surround_tbc, &stereo,
166  ret |= check_coefficient(&surround_tbc, &mono,
168 
169  return ret;
170 }
out
static FILE * out
Definition: movenc.c:55
AV_CHANNEL_LAYOUT_STEREO
#define AV_CHANNEL_LAYOUT_STEREO
Definition: channel_layout.h:395
matrix
Definition: vc1dsp.c:43
mathematics.h
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition: channel_layout.h:329
AV_CHANNEL_LAYOUT_7POINT2POINT3
#define AV_CHANNEL_LAYOUT_7POINT2POINT3
Definition: channel_layout.h:427
AV_CHAN_TOP_BACK_RIGHT
@ AV_CHAN_TOP_BACK_RIGHT
Definition: channel_layout.h:67
AV_CHAN_SIDE_RIGHT
@ AV_CHAN_SIDE_RIGHT
Definition: channel_layout.h:60
limits.h
swr_build_matrix2
av_cold int swr_build_matrix2(const AVChannelLayout *in_layout, const AVChannelLayout *out_layout, double center_mix_level, double surround_mix_level, double lfe_mix_level, double maxval, double rematrix_volume, double *matrix_param, ptrdiff_t stride, enum AVMatrixEncoding matrix_encoding, void *log_context)
Generate a channel mixing matrix.
Definition: rematrix.c:389
fabs
static __device__ float fabs(float a)
Definition: cuda_runtime.h:182
NULL
#define NULL
Definition: coverity.c:32
AV_CHAN_TOP_BACK_CENTER
@ AV_CHAN_TOP_BACK_CENTER
Definition: channel_layout.h:66
AV_CHANNEL_LAYOUT_5POINT1POINT2
#define AV_CHANNEL_LAYOUT_5POINT1POINT2
Definition: channel_layout.h:420
swresample.h
AV_CHAN_FRONT_RIGHT
@ AV_CHAN_FRONT_RIGHT
Definition: channel_layout.h:51
AV_CHAN_FRONT_CENTER
@ AV_CHAN_FRONT_CENTER
Definition: channel_layout.h:52
AVChannelLayout
An AVChannelLayout holds information about the channel layout of audio data.
Definition: channel_layout.h:319
AV_MATRIX_ENCODING_NONE
@ AV_MATRIX_ENCODING_NONE
Definition: channel_layout.h:261
AV_CHAN_BACK_RIGHT
@ AV_CHAN_BACK_RIGHT
Definition: channel_layout.h:55
AV_CHAN_SIDE_LEFT
@ AV_CHAN_SIDE_LEFT
Definition: channel_layout.h:59
AV_CHAN_TOP_FRONT_RIGHT
@ AV_CHAN_TOP_FRONT_RIGHT
Definition: channel_layout.h:64
MATRIX_STRIDE
#define MATRIX_STRIDE
Definition: rematrix.c:29
AVChannel
AVChannel
Definition: channel_layout.h:47
av_channel_name
int av_channel_name(char *buf, size_t buf_size, enum AVChannel channel_id)
Get a human readable string in an abbreviated form describing a given channel.
Definition: channel_layout.c:105
AV_CHANNEL_LAYOUT_5POINT1POINT4_BACK
#define AV_CHANNEL_LAYOUT_5POINT1POINT4_BACK
Definition: channel_layout.h:424
ret
ret
Definition: filter_design.txt:187
main
int main(void)
Definition: rematrix.c:91
M_SQRT1_2
#define M_SQRT1_2
Definition: mathematics.h:103
channel_layout.h
check_coefficient
static int check_coefficient(const AVChannelLayout *in_layout, const AVChannelLayout *out_layout, enum AVChannel in_channel, enum AVChannel out_channel, double expected)
Definition: rematrix.c:82
AV_CHAN_TOP_BACK_LEFT
@ AV_CHAN_TOP_BACK_LEFT
Definition: channel_layout.h:65
av_channel_layout_index_from_channel
int av_channel_layout_index_from_channel(const AVChannelLayout *channel_layout, enum AVChannel channel)
Get the index of a given channel in a channel layout.
Definition: channel_layout.c:715
AV_CHAN_BACK_LEFT
@ AV_CHAN_BACK_LEFT
Definition: channel_layout.h:54
AV_CHANNEL_LAYOUT_MONO
#define AV_CHANNEL_LAYOUT_MONO
Definition: channel_layout.h:394
AV_CHAN_TOP_FRONT_LEFT
@ AV_CHAN_TOP_FRONT_LEFT
Definition: channel_layout.h:62
AV_CHANNEL_LAYOUT_5POINT1_BACK
#define AV_CHANNEL_LAYOUT_5POINT1_BACK
Definition: channel_layout.h:407
AV_CHAN_FRONT_LEFT
@ AV_CHAN_FRONT_LEFT
Definition: channel_layout.h:50
check_coefficient_with_slev
static int check_coefficient_with_slev(const AVChannelLayout *in_layout, const AVChannelLayout *out_layout, enum AVChannel in_channel, enum AVChannel out_channel, double surround_mix_level, double expected)
Definition: rematrix.c:31
AV_CHANNEL_LAYOUT_5POINT1
#define AV_CHANNEL_LAYOUT_5POINT1
Definition: channel_layout.h:405