OpenBoard-org / OpenBoard

OpenBoard is a cross-platform interactive whiteboard application intended for use in a classroom setting.
https://openboard.ch/
GNU General Public License v3.0
2.33k stars 423 forks source link

Fails to build with ffmpeg 5.0 #561

Closed sebastinas closed 3 months ago

sebastinas commented 2 years ago

OpenBoard is incompatible with ffmpeg 5.0. Compilation fails with:

g++ -c -pipe -std=c++11 -fopenmp -Wdate-time -D_FORTIFY_SOURCE=2 -g -O2 -ffile-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -std=gnu++1y -w -D_REENTRANT -fPIC -DNO_THIRD_PARTY_WARNINGS -DUBVERSION="\"1.6.1."\" -DUBVERSION_RC=1,6,1,240,0309 -DQT_CORE_LIB -DQT_NO_DEBUG -DQT_WEBKITWIDGETS_LIB -DQT_WEBKIT_LIB -DQT_SVG_LIB -DQT_UITOOLS_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_WIDGETS_LIB -DQT_MULTIMEDIA_LIB -DQT_GUI_LIB -DQT_XMLPATTERNS_LIB -DQT_NETWORK_LIB -DQT_XML_LIB -DQT_CORE_LIB -Isrc -Isrc/web/browser -Isrc/qtsingleapplication/src -Isrc/pdf-merger -Iplugins/cffadaptor/src -I/usr/include/quazip -I/usr/include/poppler -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtWebKitWidgets -I/usr/include/x86_64-linux-gnu/qt5/QtWebKit -I/usr/include/x86_64-linux-gnu/qt5/QtSvg -I/usr/include/x86_64-linux-gnu/qt5/QtUiTools -I/usr/include/x86_64-linux-gnu/qt5/QtMultimediaWidgets -I/usr/include/x86_64-linux-gnu/qt5/QtPrintSupport -I/usr/include/x86_64-linux-gnu/qt5/QtWidgets -I/usr/include/x86_64-linux-gnu/qt5/QtMultimedia -I/usr/include/x86_64-linux-gnu/qt5/QtGui -I/usr/include/x86_64-linux-gnu/qt5/QtXmlPatterns -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5/QtXml -Ibuild/linux/release/moc -Ibuild/linux/release/ui -I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++ -o build/linux/release/objects/UBFFmpegVideoEncoder.o src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp: In function ‘void writeFrame(AVFrame*, AVPacket*, AVStream*, AVFormatContext*)’:
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:183:21: error: ‘AVStream’ {aka ‘struct AVStream’} has no member named ‘codec’
  183 |         if (stream->codec->codec_type == AVMEDIA_TYPE_AUDIO)
      |                     ^~~~~
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:184:49: error: ‘AVStream’ {aka ‘struct AVStream’} has no member named ‘codec’
  184 |             ret = avcodec_encode_audio2(stream->codec, packet, frame, &gotOutput);
      |                                                 ^~~~~
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:184:19: error: ‘avcodec_encode_audio2’ was not declared in this scope; did you mean ‘avcodec_encode_subtitle’?
  184 |             ret = avcodec_encode_audio2(stream->codec, packet, frame, &gotOutput);
      |                   ^~~~~~~~~~~~~~~~~~~~~
      |                   avcodec_encode_subtitle
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:186:49: error: ‘AVStream’ {aka ‘struct AVStream’} has no member named ‘codec’
  186 |             ret = avcodec_encode_video2(stream->codec, packet, frame, &gotOutput);
      |                                                 ^~~~~
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:186:19: error: ‘avcodec_encode_video2’ was not declared in this scope; did you mean ‘avcodec_encode_subtitle’?
  186 |             ret = avcodec_encode_video2(stream->codec, packet, frame, &gotOutput);
      |                   ^~~~~~~~~~~~~~~~~~~~~
      |                   avcodec_encode_subtitle
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:192:48: error: ‘AVStream’ {aka ‘struct AVStream’} has no member named ‘codec’
  192 |             AVRational codecTimebase = stream->codec->time_base;
      |                                                ^~~~~
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp: In member function ‘bool UBFFmpegVideoEncoder::init()’:
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:291:5: error: ‘av_register_all’ was not declared in this scope
  291 |     av_register_all();
      |     ^~~~~~~~~~~~~~~
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:292:5: error: ‘avcodec_register_all’ was not declared in this scope
  292 |     avcodec_register_all();
      |     ^~~~~~~~~~~~~~~~~~~~
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:313:48: error: invalid conversion from ‘const AVCodec*’ to ‘AVCodec*’ [-fpermissive]
  313 |     AVCodec * videoCodec = avcodec_find_encoder(mOutputFormatContext->oformat->video_codec);
      |                            ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                                                |
      |                                                const AVCodec*
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:350:19: error: ‘AVStream’ {aka ‘struct AVStream’} has no member named ‘codec’
  350 |     mVideoStream->codec = c;
      |                   ^~~~~
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:384:52: error: invalid conversion from ‘const AVCodec*’ to ‘AVCodec*’ [-fpermissive]
  384 |         AVCodec * audioCodec = avcodec_find_encoder(mOutputFormatContext->oformat->audio_codec);
      |                                ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                                                    |
      |                                                    const AVCodec*
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:394:27: error: ‘AVStream’ {aka ‘struct AVStream’} has no member named ‘codec’
  394 |         c = mAudioStream->codec;
      |                           ^~~~~
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp: In member function ‘AVFrame* UBFFmpegVideoEncoder::convertImageFrame(UBFFmpegVideoEncoder::ImageFrame)’:
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:509:37: error: ‘AVStream’ {aka ‘struct AVStream’} has no member named ‘codec’
  509 |     avFrame->format = mVideoStream->codec->pix_fmt;
      |                                     ^~~~~
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:510:36: error: ‘AVStream’ {aka ‘struct AVStream’} has no member named ‘codec’
  510 |     avFrame->width = mVideoStream->codec->width;
      |                                    ^~~~~
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:511:37: error: ‘AVStream’ {aka ‘struct AVStream’} has no member named ‘codec’
  511 |     avFrame->height = mVideoStream->codec->height;
      |                                     ^~~~~
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:519:72: error: ‘AVStream’ {aka ‘struct AVStream’} has no member named ‘codec’
  519 |     if (av_image_alloc(avFrame->data, avFrame->linesize, mVideoStream->codec->width,
      |                                                                        ^~~~~
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:520:38: error: ‘AVStream’ {aka ‘struct AVStream’} has no member named ‘codec’
  520 |                        mVideoStream->codec->height, mVideoStream->codec->pix_fmt, 32) < 0)
      |                                      ^~~~~
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:520:67: error: ‘AVStream’ {aka ‘struct AVStream’} has no member named ‘codec’
  520 |                        mVideoStream->codec->height, mVideoStream->codec->pix_fmt, 32) < 0)
      |                                                                   ^~~~~
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:530:29: error: ‘AVStream’ {aka ‘struct AVStream’} has no member named ‘codec’
  530 |               mVideoStream->codec->height,
      |                             ^~~~~
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp: In member function ‘void UBFFmpegVideoEncoder::processAudio(QByteArray&)’:
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:551:50: error: ‘AVStream’ {aka ‘struct AVStream’} has no member named ‘codec’
  551 |     AVCodecContext* codecContext = mAudioStream->codec;
      |                                                  ^~~~~
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp: In member function ‘void UBFFmpegVideoEncoder::finishEncoding()’:
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:656:33: error: ‘AVStream’ {aka ‘struct AVStream’} has no member named ‘codec’
  656 |     avcodec_close(mVideoStream->codec);
      |                                 ^~~~~
src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp:660:37: error: ‘AVStream’ {aka ‘struct AVStream’} has no member named ‘codec’
  660 |         avcodec_close(mAudioStream->codec);
      |                                     ^~~~~
make[2]: *** [Makefile.Release:6142: build/linux/release/objects/UBFFmpegVideoEncoder.o] Error 1
kaamui commented 2 years ago

Hi,

thanks for reporting this, good to know. ffmpeg 5 won't be a priority at all though, as we have very limited resources and important (other) migrations to handle first.

letsfindaway commented 2 years ago

The above-mentioned https://github.com/bartoszek/AUR-openboard/issues/10 seems to provide a way to explicitly refer to ffmpeg4.4 in order to avoid this problem..

fsiegert commented 2 years ago

The above-mentioned bartoszek/AUR-openboard#10 seems to provide a way to explicitly refer to ffmpeg4.4 in order to avoid this problem..

Thanks @letsfindaway. Let me point specifically to the relevant comment here: https://github.com/bartoszek/AUR-openboard/pull/11#issuecomment-1074858168 and, for everyone not familiar with Archlinux packaging, it boils down to this patch:

https://aur.archlinux.org/cgit/aur.git/tree/ffmpeg.patch?h=openboard

Of course this only helps if your distribution is providing a legacy version of ffpmeg4 in some directory. Upstream, in OpenBoard, one could make the cmake files more flexible such that the include/lib path of ffmpeg can be specified in the cmake command line. That way it will be more straightforward for distributions/users to select ffmpeg4 without patching.

letsfindaway commented 2 years ago

Hi @fsiegert, I'm a fan of not including any system dependent paths in a build file such as cmake or here the qmake project files. Instead use the features of pkg-config to determine the correct paths whenever possible.

Some distros already use a patch to use pkgconfig for ffmpeg. See e.g. here for the patch used in the builds for openSUSE, but the same patch also appears elsewhere. It is even included in @JBBgameich's pull request https://github.com/OpenBoard-org/OpenBoard/pull/211 (already from 2019, three years old) as a single commit (https://github.com/OpenBoard-org/OpenBoard/pull/211/commits/2a93d128a0f8b79219d9436c65a70cbab8e9fd66). You see that all paths and all additional indirect dependencies of ffmpeg are gone and are replaced by a single line.

With Arch and probably others there will still be the question how to select version 4 or 5. I have checked the AUR package content for both packages. For ffmpeg5, the pkgconfig files are in the standard path /usr/lib/pkgconfig. For ffmpeg4 they are in usr/lib/ffmpeg4.4/pkgconfig. So you still have to tell the system where to search. You can however do that using the PKG_CONFIG_PATH environment variable. See the manual page of pkg-config for details.

So my proposal would be to upstream the referenced patch. @kaamui: would this work for all of your environments?

letsfindaway commented 2 years ago

Now I see that Qt also seems to have a dependency to ffmpeg, and of course we have to use the same version when building OpenBoard. So the only solution would be to port away from the already deprecated codec field. Some pointers how to do this might be in https://stackoverflow.com/questions/71565636/replacing-deprecated-avstream-codec-parameter-in-libav.

See also the example at https://libav.org/documentation/doxygen/master/encode_video_8c-example.html. Note that using the new API will work with both, version 4 and 5. The old API was already deprecated in version 4.

letsfindaway commented 3 months ago

This issue is resolved with PR #610