PDA

View Full Version : Undefined Reference for 1 of many constructors for QVideoFrame



robadob
24th November 2013, 22:30
I've come across a weird issue while trying to convert an FFMPeg AVFrame to a QT QVideoFrame;

I'm trying to create the QVideoFrame using this constructor


QVideoFrame(int bytes, const QSize &size, int bytesPerLine, PixelFormat format);
It compiles fine, however at link I receive the issue;


~myfile.cpp:130: undefined reference to `_imp___ZN11QVideoFrameC1EiRK5QSizeiNS_13AVPixelFo rmatE'
collect2.exe: error: ld returned 1 exit status
(As it's a linker issue, I'm presuming you won't want code examples).

I've compiled QT 4.8.5 myself using mingw32 and the other constructors (no params and QImage param) for QVideoFrame that I've tested compile and link correctly. From looking at the QT sources there is nothing that stands out as different for this constructor for it to not be included in the library.

At this point I'm trying to implement an extension of QAbstractVideoBuffer so I can use that constructor, however that's proving harder than it should be & I'd love to understand why this issue is occurring.

Thanks

I'm really stumped with this so I've also got it on StackOverflow (http://stackoverflow.com/questions/20181673/undefined-reference-for-1-of-many-constructors-for-qvideoframe) at the moment.

ChrisW67
24th November 2013, 22:36
Does your PRO file contain:


QT += multimedia

and have you run qmake since adding that line?

robadob
24th November 2013, 22:39
Does your PRO file contain:


QT += multimedia

and have you run qmake since adding that line?
Yes, otherwise it wouldn't compile and link when I use the other constructors for QVideoFrame.

ChrisW67
25th November 2013, 01:52
People are quite good at stuffing about until something compiles, i.e. by using full paths in #include or settings INCLUDEPATH, and then failing at link because of a lack of understanding. They are also good as giving a description of the problem that is coloured by their assumptions. I like to look for the obvious before looking for the not obvious.

Your assessment of the QVideoFrame sources certainly imply that the constructor is both public and, by virtue of the class, exported. The message seems consistent with the symbol either not being present or not being exported. There does not seem to be a way for the implementation to have been pre-processed out.

Is there any chance the linker is picking up a very old Qt4 library? (It's a long shot).

If your MinGW tool chain has the "nm" command, does the output of:


nm -D \path\to\QtMultimedia4.dll

contain "_ZN11QVideoFrameC1EiRK5QSizeiNS_13AVPixelFormatE"?
Edit: Just checked, and there are no symbols visible through nm in my off-the-shelf Qt 4.8.4

robadob
25th November 2013, 08:13
People are quite good at stuffing about until something compiles, i.e. by using full paths in #include or settings INCLUDEPATH, and then failing at link because of a lack of understanding. They are also good as giving a description of the problem that is coloured by their assumptions. I like to look for the obvious before looking for the not obvious.

Your assessment of the QVideoFrame sources certainly imply that the constructor is both public and, by virtue of the class, exported. The message seems consistent with the symbol either not being present or not being exported. There does not seem to be a way for the implementation to have been pre-processed out.

Is there any chance the linker is picking up a very old Qt4 library? (It's a long shot).

If your MinGW tool chain has the "nm" command, does the output of:


nm -D \path\to\QtMultimedia4.dll

contain "_ZN11QVideoFrameC1EiRK5QSizeiNS_13AVPixelFormatE"?
Edit: Just checked, and there are no symbols visible through nm in my off-the-shelf Qt 4.8.4
I also receive no symbols when running that command on my QtMultimedia.dll.

I'm pretty confident that I am not compiling/linking to the wrong QT, as previously I was developing under Visual Studio until I ran into some ffmpeg incompatibilities, so this is the only copy of Mingw compiled QT I have around.

With regard to whether the function is not exported;


QVideoFrame();
QVideoFrame(QAbstractVideoBuffer *buffer, const QSize &size, PixelFormat format);
QVideoFrame(int bytes, const QSize &size, int bytesPerLine, PixelFormat format); //This one
QVideoFrame(const QImage &image);
QVideoFrame(const QVideoFrame &other);
~QVideoFrame();
That is from qvideoframe.h, and the constructor I desire is declared no different to those that work, so I can't see why it would not be exported. Perhaps you know of the necessary configure parameters to make exports visible?/not name mangled?

aamer4yu
25th November 2013, 09:30
QVideoFrame(int bytes, const QSize &size, int bytesPerLine, PixelFormat format);

Is this how you are creating the object ?
It mereley says you are declaring a function QVideoFrame with given parameters. May be thats why you are getting the linking error since it cannot find the implementation of the function.

I guess it should be something like -
QVideoFrame vf(bytes, size, bytesPerLine, format);

robadob
25th November 2013, 12:04
Is this how you are creating the object ?
It mereley says you are declaring a function QVideoFrame with given parameters. May be thats why you are getting the linking error since it cannot find the implementation of the function.

I guess it should be something like -
QVideoFrame vf(bytes, size, bytesPerLine, format);

That is just the constructors prototype, i'm actually declaring it with;



QVideoFrame* qframe;
QVideoFrame::PixelFormat qpf = parseFormat(pCodecCtx->pix_fmt);
const QSize *framesize = new QSize(pCodecCtx->width, pCodecCtx->height);
qframe = new QVideoFrame (pFrame->pkt_size, *framesize, pFrame->linesize[0], qpf);

I would have thought if this was incorrect, I would receive a compile error, and changing it to use the other constructors would provide a similar error, whereas those which I've tried work.

Edit:
Additionally I've just changed the declaration to the form;


QVideoFrame qframe(pFrame->pkt_size, *framesize, pFrame->linesize[0], qpf);

and I receive exactly the same linker error.

robadob
25th November 2013, 17:53
I've just tested whether i would be able to use the constructor;

QVideoFrame ( QAbstractVideoBuffer * buffer, const QSize & size, PixelFormat format )
As the constructor i wish to use, makes the `buffer` from the data I pass to it, this then gave me a similar linker error;


~myfile.cpp:146: undefined reference to `_imp___ZN11QVideoFrameC1EP20QAbstractVideoBufferR K5QSizeNS_13AVPixelFormatE'
collect2.exe: error: ld returned 1 exit status


This is really confusing me now, as the only other constructors (ignoring the copy constructor);


QVideoFrame ( const QImage & image )
QVideoFrame ( const QVideoFrame & other )

Both compile/link without fault and are unsuitable for my usage, is it possible that parts of QVideoFrame have silently failed to compile?
Checking back through the QVideoFrame class from its inception in qt4.6-4.8 they all have the 4 constructors, so I still see no reason for 2 to be missing :s

Added after 12 minutes:


People are quite good at stuffing about until something compiles, i.e. by using full paths in #include or settings INCLUDEPATH, and then failing at link because of a lack of understanding. They are also good as giving a description of the problem that is coloured by their assumptions. I like to look for the obvious before looking for the not obvious.

Your assessment of the QVideoFrame sources certainly imply that the constructor is both public and, by virtue of the class, exported. The message seems consistent with the symbol either not being present or not being exported. There does not seem to be a way for the implementation to have been pre-processed out.

Is there any chance the linker is picking up a very old Qt4 library? (It's a long shot).

If your MinGW tool chain has the "nm" command, does the output of:


nm -D \path\to\QtMultimedia4.dll

contain "_ZN11QVideoFrameC1EiRK5QSizeiNS_13AVPixelFormatE"?
Edit: Just checked, and there are no symbols visible through nm in my off-the-shelf Qt 4.8.4
Edit2: I played with the params of nm and I found that;

nm -a -C auto QtMultimediad4.dll
returns


64dc943e T QVideoFrame::QVideoFrame(int, QSize const&, int, QVideoFrame::PixelFormat)
64dc93e8 T QVideoFrame::QVideoFrame(QAbstractVideoBuffer*, QSize const&, QVideoFrame::PixelFormat)
64dc9534 T QVideoFrame::QVideoFrame(QImage const&)
64dc9610 T QVideoFrame::QVideoFrame(QVideoFrame const&)
64dc93b4 T QVideoFrame::QVideoFrame()
64dc943e T QVideoFrame::QVideoFrame(int, QSize const&, int, QVideoFrame::PixelFormat)
64dc93e8 T QVideoFrame::QVideoFrame(QAbstractVideoBuffer*, QSize const&, QVideoFrame::PixelFormat)
64dc9534 T QVideoFrame::QVideoFrame(QImage const&)
64dc9610 T QVideoFrame::QVideoFrame(QVideoFrame const&)
64dc93b4 T QVideoFrame::QVideoFrame()
64dc9654 T QVideoFrame::~QVideoFrame()
64dc9654 T QVideoFrame::~QVideoFrame()

and without the name mangling fix parameter;


64dc943e T __ZN11QVideoFrameC1EiRK5QSizeiNS_11PixelFormatE
64dc93e8 T __ZN11QVideoFrameC1EP20QAbstractVideoBufferRK5QSiz eNS_11PixelFormatE
64dc9534 T __ZN11QVideoFrameC1ERK6QImage
64dc9610 T __ZN11QVideoFrameC1ERKS_
64dc93b4 T __ZN11QVideoFrameC1Ev
64dc943e T __ZN11QVideoFrameC2EiRK5QSizeiNS_11PixelFormatE
64dc93e8 T __ZN11QVideoFrameC2EP20QAbstractVideoBufferRK5QSiz eNS_11PixelFormatE
64dc9534 T __ZN11QVideoFrameC2ERK6QImage
64dc9610 T __ZN11QVideoFrameC2ERKS_
64dc93b4 T __ZN11QVideoFrameC2Ev
64dc9654 T __ZN11QVideoFrameD1Ev
64dc9654 T __ZN11QVideoFrameD2Ev

This seems to show the debug symbols for them exist, despite the -D parameter returning nothing for any qt dll, albeit the name mangled versions being different (presumably due to them being debug symbols).

robadob
25th November 2013, 23:11
I decided to take the code into isolation and see if i could make the issue happen, so that I could post something here for people to play with. It compiled/linked fine, so I commented everything out in my own code and it compiled fine. I've now traced it back to my ffmpeg imports causing the issue, if any of these includes are uncommented (other than the last one) the linker issue occurs;



extern "C" {
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfiltergraph.h>
#include <libavfilter/avcodec.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libavdevice/avdevice.h>
#include <libavutil/dict.h>
}


Still not sure why this would be happening though.

d_stranz
25th November 2013, 23:37
Are your ffmpeg libraries compatible with your Qt and app? That is, produced using the same version of the compiler you're using? I do not know if Qt's video support uses ffmpeg, but if it does, and if it uses a different compilation (or compilation flags) that may be the problem. (Although I would still be puzzled why something doesn't show up at compile time, unless one of the ffmpeg headers contains a #pragma that forces a link-time condition).

robadob
26th November 2013, 00:09
As far as I'm aware QT does not use ffmpeg (I haven't seen it mentioned anywhere, I think it uses something called Phonos).
Due to the quirky nature of ffmpeg, building it yourself is a right pain, so I'm just using the version off http://ffmpeg.zeranoe.com/builds/ (32bit dev). Might also be worth noting ffmpeg is a purely C library, so I'm not sure if the compiler incompatibility still applies.
I also read on the FAQ that ffmpeg links statically by default, if you think that would cause any issues.
I'll try and take a look through one of the headers and all it's imports.

Added after 12 minutes:

I've finally solved this by calling the ffmpeg imports after all the QT imports, presumably one of the system headers was being called from inside the extern "C" of ffmpeg.