FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/avfft.c
Date: 2024-04-20 14:10:07
Exec Total Coverage
Lines: 0 133 0.0%
Functions: 0 15 0.0%
Branches: 0 56 0.0%

Line Branch Exec Source
1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <stddef.h>
20 #include <string.h>
21
22 #include "libavutil/attributes.h"
23 #include "libavutil/macros.h"
24 #include "libavutil/mem.h"
25 #include "libavutil/tx.h"
26 #include "avfft.h"
27
28 typedef struct AVTXWrapper {
29 AVTXContext *ctx;
30 av_tx_fn fn;
31
32 AVTXContext *ctx2;
33 av_tx_fn fn2;
34
35 ptrdiff_t stride;
36 int len;
37 int inv;
38
39 float *tmp;
40 int out_of_place;
41 } AVTXWrapper;
42
43 /* FFT */
44
45 FFTContext *av_fft_init(int nbits, int inverse)
46 {
47 int ret;
48 float scale = 1.0f;
49 AVTXWrapper *s = av_mallocz(sizeof(*s));
50 if (!s)
51 return NULL;
52
53 ret = av_tx_init(&s->ctx, &s->fn, AV_TX_FLOAT_FFT, inverse, 1 << nbits,
54 &scale, AV_TX_INPLACE);
55 if (ret < 0) {
56 av_free(s);
57 return NULL;
58 }
59
60 return (FFTContext *)s;
61 }
62
63 void av_fft_permute(FFTContext *s, FFTComplex *z)
64 {
65 /* Empty */
66 }
67
68 void av_fft_calc(FFTContext *s, FFTComplex *z)
69 {
70 AVTXWrapper *w = (AVTXWrapper *)s;
71 w->fn(w->ctx, z, (void *)z, sizeof(AVComplexFloat));
72 }
73
74 av_cold void av_fft_end(FFTContext *s)
75 {
76 if (s) {
77 AVTXWrapper *w = (AVTXWrapper *)s;
78 av_tx_uninit(&w->ctx);
79 av_tx_uninit(&w->ctx2);
80 av_free(w);
81 }
82 }
83
84 FFTContext *av_mdct_init(int nbits, int inverse, double scale)
85 {
86 int ret;
87 float scale_f = scale;
88 AVTXWrapper *s = av_mallocz(sizeof(*s));
89 if (!s)
90 return NULL;
91
92 ret = av_tx_init(&s->ctx, &s->fn, AV_TX_FLOAT_MDCT, inverse, 1 << (nbits - 1), &scale_f, 0);
93 if (ret < 0) {
94 av_free(s);
95 return NULL;
96 }
97
98 if (inverse) {
99 ret = av_tx_init(&s->ctx2, &s->fn2, AV_TX_FLOAT_MDCT, inverse, 1 << (nbits - 1),
100 &scale_f, AV_TX_FULL_IMDCT);
101 if (ret < 0) {
102 av_tx_uninit(&s->ctx);
103 av_free(s);
104 return NULL;
105 }
106 }
107
108 return (FFTContext *)s;
109 }
110
111 void av_imdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input)
112 {
113 AVTXWrapper *w = (AVTXWrapper *)s;
114 w->fn2(w->ctx2, output, (void *)input, sizeof(float));
115 }
116
117 void av_imdct_half(FFTContext *s, FFTSample *output, const FFTSample *input)
118 {
119 AVTXWrapper *w = (AVTXWrapper *)s;
120 w->fn(w->ctx, output, (void *)input, sizeof(float));
121 }
122
123 void av_mdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input)
124 {
125 AVTXWrapper *w = (AVTXWrapper *)s;
126 w->fn(w->ctx, output, (void *)input, sizeof(float));
127 }
128
129 av_cold void av_mdct_end(FFTContext *s)
130 {
131 if (s) {
132 AVTXWrapper *w = (AVTXWrapper *)s;
133 av_tx_uninit(&w->ctx2);
134 av_tx_uninit(&w->ctx);
135 av_free(w);
136 }
137 }
138
139 RDFTContext *av_rdft_init(int nbits, enum RDFTransformType trans)
140 {
141 int ret;
142 float scale = trans == IDFT_C2R ? 0.5f : 1.0f;
143 AVTXWrapper *s;
144
145 /* The other 2 modes are unconventional, do not form an orthogonal
146 * transform, have never been useful, and so they're not implemented. */
147 if (trans != IDFT_C2R && trans != DFT_R2C)
148 return NULL;
149
150 s = av_mallocz(sizeof(*s));
151 if (!s)
152 return NULL;
153
154 ret = av_tx_init(&s->ctx, &s->fn, AV_TX_FLOAT_RDFT, trans == IDFT_C2R,
155 1 << nbits, &scale, 0x0);
156 if (ret < 0) {
157 av_free(s);
158 return NULL;
159 }
160
161 s->stride = (trans == DFT_C2R) ? sizeof(AVComplexFloat) : sizeof(float);
162 s->len = 1 << nbits;
163 s->inv = trans == IDFT_C2R;
164
165 s->tmp = av_malloc((s->len + 2)*sizeof(float));
166 if (!s->tmp) {
167 av_tx_uninit(&s->ctx);
168 av_free(s);
169 return NULL;
170 }
171
172 return (RDFTContext *)s;
173 }
174
175 void av_rdft_calc(RDFTContext *s, FFTSample *data)
176 {
177 AVTXWrapper *w = (AVTXWrapper *)s;
178 float *src = w->inv ? w->tmp : (float *)data;
179 float *dst = w->inv ? (float *)data : w->tmp;
180
181 if (w->inv) {
182 memcpy(src, data, w->len*sizeof(float));
183
184 src[w->len] = src[1];
185 src[1] = 0.0f;
186 }
187
188 w->fn(w->ctx, dst, (void *)src, w->stride);
189
190 if (!w->inv) {
191 dst[1] = dst[w->len];
192 memcpy(data, dst, w->len*sizeof(float));
193 }
194 }
195
196 av_cold void av_rdft_end(RDFTContext *s)
197 {
198 if (s) {
199 AVTXWrapper *w = (AVTXWrapper *)s;
200 av_tx_uninit(&w->ctx);
201 av_free(w->tmp);
202 av_free(w);
203 }
204 }
205
206 DCTContext *av_dct_init(int nbits, enum DCTTransformType inverse)
207 {
208 int ret;
209 const float scale_map[] = {
210 [DCT_II] = 0.5f,
211 [DCT_III] = 1.0f / (1 << nbits),
212 [DCT_I] = 0.5f,
213 [DST_I] = 2.0f,
214 };
215 static const enum AVTXType type_map[] = {
216 [DCT_II] = AV_TX_FLOAT_DCT,
217 [DCT_III] = AV_TX_FLOAT_DCT,
218 [DCT_I] = AV_TX_FLOAT_DCT_I,
219 [DST_I] = AV_TX_FLOAT_DST_I,
220 };
221
222 AVTXWrapper *s = av_mallocz(sizeof(*s));
223 if (!s)
224 return NULL;
225
226 s->len = (1 << nbits);
227 s->out_of_place = (inverse == DCT_I) || (inverse == DST_I);
228
229 ret = av_tx_init(&s->ctx, &s->fn, type_map[inverse],
230 (inverse == DCT_III), 1 << (nbits - (inverse == DCT_III)),
231 &scale_map[inverse], s->out_of_place ? 0 : AV_TX_INPLACE);
232 if (ret < 0) {
233 av_free(s);
234 return NULL;
235 }
236
237 if (s->out_of_place) {
238 s->tmp = av_malloc((1 << (nbits + 1))*sizeof(float));
239 if (!s->tmp) {
240 av_tx_uninit(&s->ctx);
241 av_free(s);
242 return NULL;
243 }
244 }
245
246 return (DCTContext *)s;
247 }
248
249 void av_dct_calc(DCTContext *s, FFTSample *data)
250 {
251 AVTXWrapper *w = (AVTXWrapper *)s;
252 if (w->out_of_place) {
253 memcpy(w->tmp, data, w->len*sizeof(float));
254 w->fn(w->ctx, (void *)data, w->tmp, sizeof(float));
255 } else {
256 w->fn(w->ctx, data, (void *)data, sizeof(float));
257 }
258 }
259
260 av_cold void av_dct_end(DCTContext *s)
261 {
262 if (s) {
263 AVTXWrapper *w = (AVTXWrapper *)s;
264 av_tx_uninit(&w->ctx);
265 av_free(w->tmp);
266 av_free(w);
267 }
268 }
269