FFmpeg
avfft.c
Go to the documentation of this file.
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 {
31 
34 
35  ptrdiff_t stride;
36  int len;
37  int inv;
38 
39  float *tmp;
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,
55  if (ret < 0) {
56  av_free(s);
57  return NULL;
58  }
59 
60  return (FFTContext *)s;
61 }
62 
64 {
65  /* Empty */
66 }
67 
69 {
70  AVTXWrapper *w = (AVTXWrapper *)s;
71  w->fn(w->ctx, z, (void *)z, sizeof(AVComplexFloat));
72 }
73 
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 
112 {
113  AVTXWrapper *w = (AVTXWrapper *)s;
114  w->fn2(w->ctx2, output, (void *)input, sizeof(float));
115 }
116 
118 {
119  AVTXWrapper *w = (AVTXWrapper *)s;
120  w->fn(w->ctx, output, (void *)input, sizeof(float));
121 }
122 
124 {
125  AVTXWrapper *w = (AVTXWrapper *)s;
126  w->fn(w->ctx, output, (void *)input, sizeof(float));
127 }
128 
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 
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(float) : sizeof(AVComplexFloat);
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 
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 
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 
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[] = {
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 
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 
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 }
AVTXWrapper::len
int len
Definition: avfft.c:36
DCT_I
@ DCT_I
Definition: avfft.h:121
RDFTContext
struct RDFTContext RDFTContext
Definition: avfft.h:98
AVTXWrapper::inv
int inv
Definition: avfft.c:37
av_dct_calc
void av_dct_calc(DCTContext *s, FFTSample *data)
Definition: avfft.c:249
inverse
inverse
Definition: af_crystalizer.c:121
av_fft_calc
void av_fft_calc(FFTContext *s, FFTComplex *z)
Do a complex FFT with the parameters defined in av_fft_init().
Definition: avfft.c:68
AVTXContext
Definition: tx_priv.h:235
output
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce output
Definition: filter_design.txt:225
DFT_C2R
@ DFT_C2R
Definition: avfft.h:95
w
uint8_t w
Definition: llviddspenc.c:38
data
const char data[16]
Definition: mxf.c:148
AVComplexFloat
Definition: tx.h:27
AVTXWrapper::fn
av_tx_fn fn
Definition: avfft.c:30
av_imdct_half
void av_imdct_half(FFTContext *s, FFTSample *output, const FFTSample *input)
Definition: avfft.c:117
AVTXWrapper
Definition: avfft.c:28
av_tx_init
av_cold int av_tx_init(AVTXContext **ctx, av_tx_fn *tx, enum AVTXType type, int inv, int len, const void *scale, uint64_t flags)
Initialize a transform context with the given configuration (i)MDCTs with an odd length are currently...
Definition: tx.c:901
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
AVTXWrapper::ctx2
AVTXContext * ctx2
Definition: avfft.c:32
DCT_III
@ DCT_III
Definition: avfft.h:120
macros.h
IDFT_C2R
@ IDFT_C2R
Definition: avfft.h:93
scale
static av_always_inline float scale(float x, float s)
Definition: vf_v360.c:1389
AVTXWrapper::stride
ptrdiff_t stride
Definition: avfft.c:35
FFTContext
struct FFTContext FFTContext
Definition: avfft.h:45
av_mdct_end
av_cold void av_mdct_end(FFTContext *s)
Definition: avfft.c:129
av_cold
#define av_cold
Definition: attributes.h:90
av_tx_fn
void(* av_tx_fn)(AVTXContext *s, void *out, void *in, ptrdiff_t stride)
Function pointer to a function to perform the transform.
Definition: tx.h:151
float
float
Definition: af_crystalizer.c:121
AV_TX_FLOAT_MDCT
@ AV_TX_FLOAT_MDCT
Standard MDCT with a sample data type of float, double or int32_t, respecively.
Definition: tx.h:68
s
#define s(width, name)
Definition: cbs_vp9.c:198
av_mdct_calc
void av_mdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input)
Definition: avfft.c:123
AV_TX_FLOAT_FFT
@ AV_TX_FLOAT_FFT
Standard complex to complex FFT with sample data type of AVComplexFloat, AVComplexDouble or AVComplex...
Definition: tx.h:47
if
if(ret)
Definition: filter_design.txt:179
AV_TX_FULL_IMDCT
@ AV_TX_FULL_IMDCT
Performs a full inverse MDCT rather than leaving out samples that can be derived through symmetry.
Definition: tx.h:175
NULL
#define NULL
Definition: coverity.c:32
av_fft_init
FFTContext * av_fft_init(int nbits, int inverse)
Set up a complex FFT.
Definition: avfft.c:45
AV_TX_INPLACE
@ AV_TX_INPLACE
Allows for in-place transformations, where input == output.
Definition: tx.h:161
DFT_R2C
@ DFT_R2C
Definition: avfft.h:92
FFTSample
float FFTSample
Definition: avfft.h:39
avfft.h
DCTContext
struct DCTContext DCTContext
Definition: avfft.h:116
av_rdft_end
av_cold void av_rdft_end(RDFTContext *s)
Definition: avfft.c:196
AVTXWrapper::ctx
AVTXContext * ctx
Definition: avfft.c:29
av_mdct_init
FFTContext * av_mdct_init(int nbits, int inverse, double scale)
Definition: avfft.c:84
AVTXWrapper::out_of_place
int out_of_place
Definition: avfft.c:40
f
f
Definition: af_crystalizer.c:121
AV_TX_FLOAT_DCT_I
@ AV_TX_FLOAT_DCT_I
Discrete Cosine Transform I.
Definition: tx.h:116
AVTXType
AVTXType
Definition: tx.h:39
attributes.h
AVTXWrapper::fn2
av_tx_fn fn2
Definition: avfft.c:33
input
and forward the test the status of outputs and forward it to the corresponding return FFERROR_NOT_READY If the filters stores internally one or a few frame for some input
Definition: filter_design.txt:172
av_tx_uninit
av_cold void av_tx_uninit(AVTXContext **ctx)
Frees a context and sets *ctx to NULL, does nothing when *ctx == NULL.
Definition: tx.c:294
DST_I
@ DST_I
Definition: avfft.h:122
av_imdct_calc
void av_imdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input)
Definition: avfft.c:111
RDFTransformType
RDFTransformType
Definition: avfft.h:91
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:254
av_dct_init
DCTContext * av_dct_init(int nbits, enum DCTTransformType inverse)
Set up DCT.
Definition: avfft.c:206
ret
ret
Definition: filter_design.txt:187
AV_TX_FLOAT_RDFT
@ AV_TX_FLOAT_RDFT
Real to complex and complex to real DFTs.
Definition: tx.h:90
AV_TX_FLOAT_DST_I
@ AV_TX_FLOAT_DST_I
Discrete Sine Transform I.
Definition: tx.h:128
mem.h
av_rdft_calc
void av_rdft_calc(RDFTContext *s, FFTSample *data)
Definition: avfft.c:175
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
av_dct_end
av_cold void av_dct_end(DCTContext *s)
Definition: avfft.c:260
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
AV_TX_FLOAT_DCT
@ AV_TX_FLOAT_DCT
Real to real (DCT) transforms.
Definition: tx.h:104
DCT_II
@ DCT_II
Definition: avfft.h:119
av_fft_end
av_cold void av_fft_end(FFTContext *s)
Definition: avfft.c:74
AVTXWrapper::tmp
float * tmp
Definition: avfft.c:39
DCTTransformType
DCTTransformType
Definition: avfft.h:118
av_rdft_init
RDFTContext * av_rdft_init(int nbits, enum RDFTransformType trans)
Set up a real FFT.
Definition: avfft.c:139
av_fft_permute
void av_fft_permute(FFTContext *s, FFTComplex *z)
Do the permutation needed BEFORE calling ff_fft_calc().
Definition: avfft.c:63
FFTComplex
Definition: avfft.h:41
tx.h