Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Including a prebuilt library



  • Hi,

    I would like to use FFT function from ffmpeg library. I downloaded a prebuilt binary and copied all files to the correct folders (lib, bin, include) in c:\qt\version\mingw53_32.

    In the .pro file I added this line:

        LIBS += -Llibavcodec
    

    Then I included the header file I need:

    #include "libavcodec/avfft.h"
    

    Later in my code I call a function defined in the header:

    ctx = av_rdft_init((int) log2(N), DFT_R2C);
    

    Everything seems to be fine until I try to compile my code. I always get this error:

    ./release\spectrummeter.o:spectrummeter.cpp:(.text+0x385): undefined reference to `av_rdft_init(int, RDFTransformType)'
    ./release\spectrummeter.o:spectrummeter.cpp:(.text+0xcec): undefined reference to `av_rdft_calc(RDFTContext*, float*)'
    collect2.exe: error: ld returned 1 exit status
    

    I don't know what is the problem. The two mentioned functions are defined in the header file and I included the library. What could be the problem? What is still missing?

    As a reference here is the complete header file avfft.h:

    /*
     * This file is part of FFmpeg.
     *
     * FFmpeg is free software; you can redistribute it and/or
     * modify it under the terms of the GNU Lesser General Public
     * License as published by the Free Software Foundation; either
     * version 2.1 of the License, or (at your option) any later version.
     *
     * FFmpeg is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     * Lesser General Public License for more details.
     *
     * You should have received a copy of the GNU Lesser General Public
     * License along with FFmpeg; if not, write to the Free Software
     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     */
    
    #ifndef AVCODEC_AVFFT_H
    #define AVCODEC_AVFFT_H
    
    /**
     * @file
     * @ingroup lavc_fft
     * FFT functions
     */
    
    /**
     * @defgroup lavc_fft FFT functions
     * @ingroup lavc_misc
     *
     * @{
     */
    
    typedef float FFTSample;
    
    typedef struct FFTComplex {
        FFTSample re, im;
    } FFTComplex;
    
    typedef struct FFTContext FFTContext;
    
    /**
     * Set up a complex FFT.
     * @param nbits           log2 of the length of the input array
     * @param inverse         if 0 perform the forward transform, if 1 perform the inverse
     */
    FFTContext *av_fft_init(int nbits, int inverse);
    
    /**
     * Do the permutation needed BEFORE calling ff_fft_calc().
     */
    void av_fft_permute(FFTContext *s, FFTComplex *z);
    
    /**
     * Do a complex FFT with the parameters defined in av_fft_init(). The
     * input data must be permuted before. No 1.0/sqrt(n) normalization is done.
     */
    void av_fft_calc(FFTContext *s, FFTComplex *z);
    
    void av_fft_end(FFTContext *s);
    
    FFTContext *av_mdct_init(int nbits, int inverse, double scale);
    void av_imdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input);
    void av_imdct_half(FFTContext *s, FFTSample *output, const FFTSample *input);
    void av_mdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input);
    void av_mdct_end(FFTContext *s);
    
    /* Real Discrete Fourier Transform */
    
    enum RDFTransformType {
        DFT_R2C,
        IDFT_C2R,
        IDFT_R2C,
        DFT_C2R,
    };
    
    typedef struct RDFTContext RDFTContext;
    
    /**
     * Set up a real FFT.
     * @param nbits           log2 of the length of the input array
     * @param trans           the type of transform
     */
    RDFTContext *av_rdft_init(int nbits, enum RDFTransformType trans);
    void av_rdft_calc(RDFTContext *s, FFTSample *data);
    void av_rdft_end(RDFTContext *s);
    
    /* Discrete Cosine Transform */
    
    typedef struct DCTContext DCTContext;
    
    enum DCTTransformType {
        DCT_II = 0,
        DCT_III,
        DCT_I,
        DST_I,
    };
    
    /**
     * Set up DCT.
     *
     * @param nbits           size of the input array:
     *                        (1 << nbits)     for DCT-II, DCT-III and DST-I
     *                        (1 << nbits) + 1 for DCT-I
     * @param type            the type of transform
     *
     * @note the first element of the input of DST-I is ignored
     */
    DCTContext *av_dct_init(int nbits, enum DCTTransformType type);
    void av_dct_calc(DCTContext *s, FFTSample *data);
    void av_dct_end (DCTContext *s);
    
    /**
     * @}
     */
    
    #endif /* AVCODEC_AVFFT_H */ 
    

  • Lifetime Qt Champion

    Hi
    Since its prebuild. Are you sure its
    for mingw 32 bit? and not say for visual studio etc ?



  • @vlada

    LIBS parameter has in your example only the path with -L declared, but the library name starting with -l is missing.
    See here



  • @mrjj I'm pretty sure I have the correct version. I need the ffmpeg libraries for QtAV and here it works correctly. I use the MinGW version from here.

    @koahnig Yes, this was definitely wrong. I fixed it like this:

    LIBS += C:/Qt/5.11.1/mingw53_32/lib/avcodec.lib
    

    but unfortunately it didn't help. I still get the same error. Unfortunately I don't fully understand how ther linker works and were are the different library files (lib/avcodec.lib, lib/libavcodec.dll.a, bin/avcodec-58.dll) used.



  • assuming you are compiling your code as c++-code it looks like a name mangling problem.

    try to change this

    #include "libavcodec/avfft.h"

    to

    extern "C" {
    #include "libavcodec/avfft.h"
    }


  • Lifetime Qt Champion

    Hi @Gerd,
    looking at the linker error:

    undefined reference to 'av_rdft_init(int, RDFTransformType)'

    I don't thing name mangling is the problem here.

    Hi @vlada,
    you should always verify your changes by looking at the linker command in Creators Compile Output.

    If your library is in C:/Qt/5.11.1/mingw53_32/lib/avcodec.lib, the .pro file should look like this: LIBS += -LC:/Qt/5.11.1/mingw53_32/lib -lavcodec

    Regards



  • @Gerd I'm not sure what is a "mangling problem" but using your code fixed the compilation.

    @aha_1980 I tried this syntax too but the result was the same. The linker command looks like this:

    g++ -Wl,-s -Wl,-subsystem,windows -mthreads -o release\Muzika.exe object_script.Muzika.Release  -lmingw32 -LC:\Qt\5.11.1\mingw53_32\lib C:\Qt\5.11.1\mingw53_32\lib\libqtmain.a -LC:\openssl\lib -LC:\Utils\my_sql\mysql-5.6.11-win32\lib -LC:\Utils\postgresql\pgsql\lib -lshell32 -LC:\Moje\QtProjects\Muzika\3rdparty\taglib\lib -ltag -LC:\Moje\QtProjects\build-MuzikaPlayer-Desktop_Qt_5_11_1_MinGW_32bit-Vydu00e1nu00ed\release -lfftreal -LC:\Moje\QtProjects\Muzika\3rdparty\mediainfo\lib -lmediainfo -lavcodec C:\Qt\5.11.1\mingw53_32\lib\libQt5Quick.a C:\Qt\5.11.1\mingw53_32\lib\libQt5Svg.a C:\Qt\5.11.1\mingw53_32\lib\libQt5Widgets.a C:\Qt\5.11.1\mingw53_32\lib\libQt5Multimedia.a -lQt5AV C:\Qt\5.11.1\mingw53_32\lib\libQt5Gui.a C:\Qt\5.11.1\mingw53_32\lib\libQt5Qml.a C:\Qt\5.11.1\mingw53_32\lib\libQt5Network.a C:\Qt\5.11.1\mingw53_32\lib\libQt5Sql.a C:\Qt\5.11.1\mingw53_32\lib\libQt5Xml.a C:\Qt\5.11.1\mingw53_32\lib\libQt5Core.a release\muzika_res.o 
    ./release\spectrummeter.o:spectrummeter.cpp:(.text+0x45d): undefined reference to `av_rdft_init(int, RDFTransformType)'
    ./release\spectrummeter.o:spectrummeter.cpp:(.text+0xf9b): undefined reference to `av_rdft_calc(RDFTContext*, float*)'
    collect2.exe: error: ld returned 1 exit status
    

    Now the program runs and even the inicialisation of FFT is working:

    ctx = av_rdft_init(11, DFT_R2C);
    

    But calling the real calculation causes a hard crash:

    av_rdft_calc(ctx, fft_data);
    

    I have no idea what is the problem here. Maybe wrong data size. I followed this guide to implement the FFT calculation. But I probably have a mistake somewhere.

    I do believe that if the library would be incorrectly linked, it would already crash at time my app calls the initialisation. Right?



  • Hi @aha_1980 ,
    the linker error gave me the hint about the problem:

    undefined reference to 'av_rdft_init(int, RDFTransformType)'
    

    If the linker complains about a missing C-Funktion i would expect

    undefined reference to 'av_rdft_init'
    

    without the parameter-types

    Hi @vlada ,
    here is a short description of name mangling name mangling.

    --I do believe that if the library would be incorrectly linked, it would already crash at time my app calls the initialisation. Right?
    Yeah, hat should be.

    Check the parameters of the call to av_rdft_init and be sure the return value is valid.
    Also, for the call to av_rdft_calc, check that fft_data has the rght format and size.


  • Lifetime Qt Champion

    @Gerd very good observation :)

    Sad that still some libraries don't provide this guard by itself.

    @vlada if you like, you can try my version of the linker command line nevertheless, as it is the more portable version.

    Regards


Log in to reply