tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

avfft.c (6577B)


      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 }