aboutsummaryrefslogtreecommitdiff
path: root/academic/openboard
diff options
context:
space:
mode:
authorWilly Sudiarto Raharjo <willysr@slackbuilds.org>2022-10-13 06:57:18 +0700
committerWilly Sudiarto Raharjo <willysr@slackbuilds.org>2022-10-13 10:19:15 +0700
commit7b49360918fca1c59a53dc850e603aa43fc75975 (patch)
treebf86bf28f01cfc26822538b8b2a24cc6b7fcaac2 /academic/openboard
parent77b97e1d589d043d353067d70f1abfbdd142f13a (diff)
academic/openboard: Fix build with newer ffmpeg.
Signed-off-by: Willy Sudiarto Raharjo <willysr@slackbuilds.org>
Diffstat (limited to 'academic/openboard')
-rw-r--r--academic/openboard/31755fe30cf.patch505
-rw-r--r--academic/openboard/openboard.SlackBuild5
2 files changed, 509 insertions, 1 deletions
diff --git a/academic/openboard/31755fe30cf.patch b/academic/openboard/31755fe30cf.patch
new file mode 100644
index 000000000000..948fe30d0642
--- /dev/null
+++ b/academic/openboard/31755fe30cf.patch
@@ -0,0 +1,505 @@
+From c5f8d4b5b7d43c99ddcd2b9bcbe4ec4b7beddad9 Mon Sep 17 00:00:00 2001
+From: letsfindaway <me@letsfindaway.de>
+Date: Wed, 18 May 2022 12:13:46 +0200
+Subject: [PATCH 1/2] fix: make UBFFmpegVideoEncoder compatible with ffmpeg-5
+
+- keep separate reference to AVCodecContext
+- copy parameters to AVCodecParameters
+- use new API in writeFrame
+- use AVChannelLayout
+---
+ src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp | 182 ++++++++++++++------
+ src/podcast/ffmpeg/UBFFmpegVideoEncoder.h | 2 +
+ 2 files changed, 134 insertions(+), 50 deletions(-)
+
+diff --git a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp
+index 0e4829c49..4fd84d740 100644
+--- a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp
++++ b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp
+@@ -45,20 +45,20 @@
+ AVFormatContext *s = avformat_alloc_context();
+ int ret = 0;
+
+- *avctx = NULL;
++ *avctx = nullptr;
+ if (!s)
+ goto nomem;
+
+ if (!oformat) {
+ if (format) {
+- oformat = av_guess_format(format, NULL, NULL);
++ oformat = av_guess_format(format, nullptr, nullptr);
+ if (!oformat) {
+ av_log(s, AV_LOG_ERROR, "Requested output format '%s' is not a suitable output format\n", format);
+ ret = AVERROR(EINVAL);
+ goto error;
+ }
+ } else {
+- oformat = av_guess_format(NULL, filename, NULL);
++ oformat = av_guess_format(nullptr, filename, nullptr);
+ if (!oformat) {
+ ret = AVERROR(EINVAL);
+ av_log(s, AV_LOG_ERROR, "Unable to find a suitable output format for '%s'\n",
+@@ -78,7 +78,7 @@
+ av_opt_set_defaults(s->priv_data);
+ }
+ } else
+- s->priv_data = NULL;
++ s->priv_data = nullptr;
+
+ if (filename)
+ av_strlcpy(s->filename, filename, sizeof(s->filename));
+@@ -168,15 +168,17 @@ QString avErrorToQString(int errnum)
+ /**
+ * @brief Write a given frame to the audio stream or, if a null frame is passed, flush the stream.
+ *
+- * @param frame An AVFrame to be written to the stream, or NULL to flush the stream
++ * @param frame An AVFrame to be written to the stream, or nullptr to flush the stream
+ * @param packet A (reusable) packet, used to temporarily store frame data
+ * @param stream The stream to write to
+ * @param outputFormatContext The output format context
+ */
+-void writeFrame(AVFrame *frame, AVPacket *packet, AVStream *stream, AVFormatContext *outputFormatContext)
++void writeFrame(AVFrame *frame, AVPacket *packet, AVStream *stream, AVCodecContext* c, AVFormatContext *outputFormatContext)
+ {
+- int gotOutput, ret;
++ int ret;
+
++#if LIBAVFORMAT_VERSION_MAJOR < 58
++ int gotOutput;
+ av_init_packet(packet);
+
+ do {
+@@ -200,11 +202,34 @@ void writeFrame(AVFrame *frame, AVPacket *packet, AVStream *stream, AVFormatCont
+ }
+
+ } while (gotOutput && !frame);
++#else
++ // send the frame to the encoder
++ ret = avcodec_send_frame(c, frame);
++
++ while (ret >= 0) {
++ ret = avcodec_receive_packet(c, packet);
++ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
++ break;
++ else if (ret < 0) {
++ qWarning() << "Couldn't encode audio frame: " << avErrorToQString(ret);
++ }
++
++ /* rescale output packet timestamp values from codec to stream timebase */
++ av_packet_rescale_ts(packet, c->time_base, stream->time_base);
++ packet->stream_index = stream->index;
++
++ /* Write the compressed frame to the media file. */
++ ret = av_interleaved_write_frame(outputFormatContext, packet);
++ /* pkt is now blank (av_interleaved_write_frame() takes ownership of
++ * its contents and resets pkt), so that no unreferencing is necessary.
++ * This would be different if one used av_write_frame(). */
++ }
++#endif
+ }
+
+-void flushStream(AVPacket *packet, AVStream *stream, AVFormatContext *outputFormatContext)
++void flushStream(AVPacket *packet, AVStream *stream, AVCodecContext* c, AVFormatContext *outputFormatContext)
+ {
+- writeFrame(NULL, packet, stream, outputFormatContext);
++ writeFrame(nullptr, packet, stream, c, outputFormatContext);
+ }
+
+ //-------------------------------------------------------------------------
+@@ -213,12 +238,12 @@ void flushStream(AVPacket *packet, AVStream *stream, AVFormatContext *outputForm
+
+ UBFFmpegVideoEncoder::UBFFmpegVideoEncoder(QObject* parent)
+ : UBAbstractVideoEncoder(parent)
+- , mOutputFormatContext(NULL)
+- , mSwsContext(NULL)
++ , mOutputFormatContext(nullptr)
++ , mSwsContext(nullptr)
+ , mShouldRecordAudio(true)
+- , mAudioInput(NULL)
+- , mSwrContext(NULL)
+- , mAudioOutBuffer(NULL)
++ , mAudioInput(nullptr)
++ , mSwrContext(nullptr)
++ , mAudioOutBuffer(nullptr)
+ , mAudioSampleRate(44100)
+ , mAudioFrameCount(0)
+ {
+@@ -288,16 +313,18 @@ bool UBFFmpegVideoEncoder::stop()
+
+ bool UBFFmpegVideoEncoder::init()
+ {
++#if LIBAVFORMAT_VERSION_MAJOR < 58
+ av_register_all();
+ avcodec_register_all();
++#endif
+
+- AVDictionary * options = NULL;
++ AVDictionary * options = nullptr;
+ int ret;
+
+ // Output format and context
+ // --------------------------------------
+- if (avformat_alloc_output_context2(&mOutputFormatContext, NULL,
+- "mp4", NULL) < 0)
++ if (avformat_alloc_output_context2(&mOutputFormatContext, nullptr,
++ "mp4", nullptr) < 0)
+ {
+ setLastErrorMessage("Couldn't allocate video format context");
+ return false;
+@@ -308,16 +335,25 @@ bool UBFFmpegVideoEncoder::init()
+
+ // Video codec and context
+ // -------------------------------------
+- mVideoStream = avformat_new_stream(mOutputFormatContext, 0);
++ mVideoStream = avformat_new_stream(mOutputFormatContext, nullptr);
++ if (!mVideoStream) {
++ setLastErrorMessage("Could not allocate stream");
++ return false;
++ }
+
+- AVCodec * videoCodec = avcodec_find_encoder(mOutputFormatContext->oformat->video_codec);
++ auto videoCodec = avcodec_find_encoder(mOutputFormatContext->oformat->video_codec);
+ if (!videoCodec) {
+ setLastErrorMessage("Video codec not found");
+ return false;
+ }
+
+ AVCodecContext* c = avcodec_alloc_context3(videoCodec);
++ if (!c) {
++ setLastErrorMessage("Could not allocate encoding context");
++ return false;
++ }
+
++ c->codec_id = mOutputFormatContext->oformat->video_codec;
+ c->bit_rate = videoBitsPerSecond();
+ c->width = videoSize().width();
+ c->height = videoSize().height();
+@@ -329,6 +365,8 @@ bool UBFFmpegVideoEncoder::init()
+ if (mOutputFormatContext->oformat->flags & AVFMT_GLOBALHEADER)
+ c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
+
++ mVideoStream->time_base = c->time_base;
++
+ /*
+ * Supported pixel formats for h264 are:
+ * AV_PIX_FMT_YUV420P
+@@ -347,13 +385,20 @@ bool UBFFmpegVideoEncoder::init()
+ return false;
+ }
+
+- mVideoStream->codec = c;
++ mVideoCodecContext = c;
++
++ // copy the stream parameters to the muxer
++ ret = avcodec_parameters_from_context(mVideoStream->codecpar, c);
++ if (ret < 0) {
++ setLastErrorMessage("Could not copy the stream parameters");
++ return false;
++ }
+
+ // Source images are RGB32, and should be converted to YUV for h264 video
+ mSwsContext = sws_getCachedContext(mSwsContext,
+ c->width, c->height, AV_PIX_FMT_RGB32,
+ c->width, c->height, c->pix_fmt,
+- SWS_BICUBIC, 0, 0, 0);
++ SWS_BICUBIC, nullptr, nullptr, nullptr);
+
+ // Audio codec and context
+ // -------------------------------------
+@@ -381,7 +426,7 @@ bool UBFFmpegVideoEncoder::init()
+
+ // Codec
+
+- AVCodec * audioCodec = avcodec_find_encoder(mOutputFormatContext->oformat->audio_codec);
++ auto audioCodec = avcodec_find_encoder(mOutputFormatContext->oformat->audio_codec);
+
+ if (!audioCodec) {
+ setLastErrorMessage("Audio codec not found");
+@@ -389,15 +434,29 @@ bool UBFFmpegVideoEncoder::init()
+ }
+
+ mAudioStream = avformat_new_stream(mOutputFormatContext, audioCodec);
++ if (!mAudioStream) {
++ setLastErrorMessage("Could not allocate stream");
++ return false;
++ }
++
+ mAudioStream->id = mOutputFormatContext->nb_streams-1;
+
+- c = mAudioStream->codec;
++ c = avcodec_alloc_context3(audioCodec);
++ if (!c) {
++ setLastErrorMessage("Could not allocate encoding context");
++ return false;
++ }
+
+ c->bit_rate = 96000;
+ c->sample_fmt = audioCodec->sample_fmts ? audioCodec->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;// FLTP by default for AAC
+ c->sample_rate = mAudioSampleRate;
++
++#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(57, 25, 100)
+ c->channel_layout = AV_CH_LAYOUT_STEREO;
+ c->channels = av_get_channel_layout_nb_channels(c->channel_layout);
++#else
++ av_channel_layout_copy(&c->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO);
++#endif
+
+ //deprecated on ffmpeg 4
+ c->strict_std_compliance = -2;// Enable use of experimental codec
+@@ -412,13 +471,22 @@ bool UBFFmpegVideoEncoder::init()
+ if (mOutputFormatContext->oformat->flags & AVFMT_GLOBALHEADER)
+ c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
+
+- ret = avcodec_open2(c, audioCodec, NULL);
++ ret = avcodec_open2(c, audioCodec, nullptr);
+
+ if (ret < 0) {
+ setLastErrorMessage(QString("Couldn't open audio codec: ") + avErrorToQString(ret));
+ return false;
+ }
+
++ mAudioCodecContext = c;
++
++ // copy the stream parameters to the muxer
++ ret = avcodec_parameters_from_context(mAudioStream->codecpar, c);
++ if (ret < 0) {
++ setLastErrorMessage("Could not copy the stream parameters");
++ return false;
++ }
++
+ // The input (raw sound from the microphone) may not match the codec's sampling rate,
+ // sample format or number of channels; we use libswresample to convert and resample it
+ mSwrContext = swr_alloc();
+@@ -427,15 +495,23 @@ bool UBFFmpegVideoEncoder::init()
+ return false;
+ }
+
+- av_opt_set_int(mSwrContext, "in_channel_count", inChannelCount, 0);
+- av_opt_set_int(mSwrContext, "in_channel_layout", av_get_default_channel_layout(inChannelCount), 0);
+ av_opt_set_int(mSwrContext, "in_sample_rate", inSampleRate, 0);
+ av_opt_set_sample_fmt(mSwrContext, "in_sample_fmt", (AVSampleFormat)mAudioInput->sampleFormat(), 0);
+- av_opt_set_int(mSwrContext, "out_channel_count", c->channels, 0);
+- av_opt_set_int(mSwrContext, "out_channel_layout", c->channel_layout, 0);
+ av_opt_set_int(mSwrContext, "out_sample_rate", c->sample_rate, 0);
+ av_opt_set_sample_fmt(mSwrContext, "out_sample_fmt", c->sample_fmt, 0);
+
++#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(57, 25, 100)
++ av_opt_set_int(mSwrContext, "in_channel_count", inChannelCount, 0);
++ av_opt_set_int(mSwrContext, "in_channel_layout", av_get_default_channel_layout(inChannelCount), 0);
++ av_opt_set_int(mSwrContext, "out_channel_count", c->channels, 0);
++ av_opt_set_int(mSwrContext, "out_channel_layout", c->channel_layout, 0);
++#else
++ AVChannelLayout inChannelLayout;
++ av_channel_layout_default(&inChannelLayout, inChannelCount);
++ av_opt_set_chlayout (mSwrContext, "in_chlayout", &inChannelLayout, 0);
++ av_opt_set_chlayout (mSwrContext, "out_chlayout", &c->ch_layout, 0);
++#endif
++
+ ret = swr_init(mSwrContext);
+ if (ret < 0) {
+ setLastErrorMessage(QString("Couldn't initialize the resampling context: ") + avErrorToQString(ret));
+@@ -456,7 +532,7 @@ bool UBFFmpegVideoEncoder::init()
+ }
+
+ // Write stream header
+- ret = avformat_write_header(mOutputFormatContext, NULL);
++ ret = avformat_write_header(mOutputFormatContext, nullptr);
+
+ if (ret < 0) {
+ setLastErrorMessage(QString("Couldn't write header to file: ") + avErrorToQString(ret));
+@@ -506,9 +582,9 @@ AVFrame* UBFFmpegVideoEncoder::convertImageFrame(ImageFrame frame)
+ {
+ AVFrame* avFrame = av_frame_alloc();
+
+- avFrame->format = mVideoStream->codec->pix_fmt;
+- avFrame->width = mVideoStream->codec->width;
+- avFrame->height = mVideoStream->codec->height;
++ avFrame->format = mVideoCodecContext->pix_fmt;
++ avFrame->width = mVideoCodecContext->width;
++ avFrame->height = mVideoCodecContext->height;
+ avFrame->pts = mVideoTimebase * frame.timestamp / 1000;
+
+ const uchar * rgbImage = frame.image.bits();
+@@ -516,18 +592,18 @@ AVFrame* UBFFmpegVideoEncoder::convertImageFrame(ImageFrame frame)
+ const int in_linesize[1] = { frame.image.bytesPerLine() };
+
+ // Allocate the output image
+- if (av_image_alloc(avFrame->data, avFrame->linesize, mVideoStream->codec->width,
+- mVideoStream->codec->height, mVideoStream->codec->pix_fmt, 32) < 0)
++ if (av_image_alloc(avFrame->data, avFrame->linesize, mVideoCodecContext->width,
++ mVideoCodecContext->height, mVideoCodecContext->pix_fmt, 32) < 0)
+ {
+ qWarning() << "Couldn't allocate image";
+- return NULL;
++ return nullptr;
+ }
+
+ sws_scale(mSwsContext,
+ (const uint8_t* const*)&rgbImage,
+ in_linesize,
+ 0,
+- mVideoStream->codec->height,
++ mVideoCodecContext->height,
+ avFrame->data,
+ avFrame->linesize);
+
+@@ -548,7 +624,7 @@ void UBFFmpegVideoEncoder::onAudioAvailable(QByteArray data)
+ void UBFFmpegVideoEncoder::processAudio(QByteArray &data)
+ {
+ int ret;
+- AVCodecContext* codecContext = mAudioStream->codec;
++ AVCodecContext* codecContext = mAudioCodecContext;
+
+ const char * inSamples = data.constData();
+
+@@ -559,7 +635,7 @@ void UBFFmpegVideoEncoder::processAudio(QByteArray &data)
+ int outSamplesCount = swr_get_out_samples(mSwrContext, inSamplesCount);
+
+ // Allocate output samples
+- uint8_t ** outSamples = NULL;
++ uint8_t ** outSamples = nullptr;
+ int outSamplesLineSize;
+
+ ret = av_samples_alloc_array_and_samples(&outSamples, &outSamplesLineSize,
+@@ -597,13 +673,19 @@ void UBFFmpegVideoEncoder::processAudio(QByteArray &data)
+
+ AVFrame * avFrame = av_frame_alloc();
+ avFrame->nb_samples = codecContext->frame_size;
++
++#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(57, 25, 100)
+ avFrame->channel_layout = codecContext->channel_layout;
++#else
++ av_channel_layout_copy(&avFrame->ch_layout, &codecContext->ch_layout);
++#endif
++
+ avFrame->format = codecContext->sample_fmt;
+ avFrame->sample_rate = codecContext->sample_rate;
+ avFrame->pts = mAudioFrameCount;
+
+ #if LIBAVFORMAT_VERSION_MICRO < 100
+- int buffer_size = av_samples_get_buffer_size(NULL, codecContext->channels, codecContext->frame_size, codecContext->sample_fmt, 0);
++ int buffer_size = av_samples_get_buffer_size(nullptr, codecContext->channels, codecContext->frame_size, codecContext->sample_fmt, 0);
+ audio_samples_buffer = (uint8_t*)av_malloc(buffer_size);
+ if (!audio_samples_buffer) {
+ qWarning() << "Couldn't allocate samples for audio frame: " << avErrorToQString(ret);
+@@ -645,19 +727,19 @@ void UBFFmpegVideoEncoder::finishEncoding()
+ {
+ qDebug() << "VideoEncoder::finishEncoding called";
+
+- flushStream(mVideoWorker->mVideoPacket, mVideoStream, mOutputFormatContext);
++ flushStream(mVideoWorker->mVideoPacket, mVideoStream, mVideoCodecContext, mOutputFormatContext);
+
+ if (mShouldRecordAudio)
+- flushStream(mVideoWorker->mAudioPacket, mAudioStream, mOutputFormatContext);
++ flushStream(mVideoWorker->mAudioPacket, mAudioStream, mAudioCodecContext, mOutputFormatContext);
+
+ av_write_trailer(mOutputFormatContext);
+ avio_close(mOutputFormatContext->pb);
+
+- avcodec_close(mVideoStream->codec);
++ avcodec_close(mVideoCodecContext);
+ sws_freeContext(mSwsContext);
+
+ if (mShouldRecordAudio) {
+- avcodec_close(mAudioStream->codec);
++ avcodec_close(mAudioCodecContext);
+ swr_free(&mSwrContext);
+ }
+
+@@ -676,17 +758,17 @@ UBFFmpegVideoEncoderWorker::UBFFmpegVideoEncoderWorker(UBFFmpegVideoEncoder* con
+ {
+ mStopRequested = false;
+ mIsRunning = false;
+- mVideoPacket = new AVPacket();
+- mAudioPacket = new AVPacket();
++ mVideoPacket = av_packet_alloc();
++ mAudioPacket = av_packet_alloc();
+ }
+
+ UBFFmpegVideoEncoderWorker::~UBFFmpegVideoEncoderWorker()
+ {
+ if (mVideoPacket)
+- delete mVideoPacket;
++ av_packet_free(&mVideoPacket);
+
+ if (mAudioPacket)
+- delete mAudioPacket;
++ av_packet_free(&mAudioPacket);
+ }
+
+ void UBFFmpegVideoEncoderWorker::stopEncoding()
+@@ -743,7 +825,7 @@ void UBFFmpegVideoEncoderWorker::runEncoding()
+ void UBFFmpegVideoEncoderWorker::writeLatestVideoFrame()
+ {
+ AVFrame* frame = mImageQueue.dequeue();
+- writeFrame(frame, mVideoPacket, mController->mVideoStream, mController->mOutputFormatContext);
++ writeFrame(frame, mVideoPacket, mController->mVideoStream, mController->mVideoCodecContext, mController->mOutputFormatContext);
+ av_freep(&frame->data[0]);
+ av_frame_free(&frame);
+ }
+@@ -751,14 +833,14 @@ void UBFFmpegVideoEncoderWorker::writeLatestVideoFrame()
+ void UBFFmpegVideoEncoderWorker::writeLatestAudioFrame()
+ {
+ AVFrame *frame = mAudioQueue.dequeue();
+- writeFrame(frame, mAudioPacket, mController->mAudioStream, mController->mOutputFormatContext);
++ writeFrame(frame, mAudioPacket, mController->mAudioStream, mController->mAudioCodecContext, mController->mOutputFormatContext);
+ av_frame_free(&frame);
+
+ #if LIBAVFORMAT_VERSION_MICRO < 100
+ if (audio_samples_buffer) {
+ av_free(audio_samples_buffer);
+ av_freep(&frame->data[0]);
+- audio_samples_buffer = NULL;
++ audio_samples_buffer = nullptr;
+ }
+ #endif
+ }
+diff --git a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h
+index 1e8a12cfa..14b735064 100644
+--- a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h
++++ b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h
+@@ -123,6 +123,7 @@ private slots:
+
+ // Video
+ // ------------------------------------------
++ AVCodecContext* mVideoCodecContext;
+ QQueue<ImageFrame> mPendingFrames;
+ struct SwsContext * mSwsContext;
+
+@@ -133,6 +134,7 @@ private slots:
+ bool mShouldRecordAudio;
+
+ UBMicrophoneInput * mAudioInput;
++ AVCodecContext* mAudioCodecContext;
+ struct SwrContext * mSwrContext;
+ /// Queue for audio that has been rescaled/converted but not encoded yet
+ AVAudioFifo *mAudioOutBuffer;
+
+From 347af2a56804100c589766ff20768914d8a04903 Mon Sep 17 00:00:00 2001
+From: letsfindaway <me@letsfindaway.de>
+Date: Thu, 15 Sep 2022 11:55:17 +0200
+Subject: [PATCH 2/2] fix: avoid taking address of initializer list
+
+- FFmpeg example code was used for UBFFmpegVideoEncoder.cpp
+- channel layout was initialized by taking address of an initializer
+- at least for some compilers this fails, as it is an rvalue
+- using an explicit variable avoids this
+---
+ src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp
+index 4fd84d740..805ff77e1 100644
+--- a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp
++++ b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp
+@@ -455,7 +455,8 @@ bool UBFFmpegVideoEncoder::init()
+ c->channel_layout = AV_CH_LAYOUT_STEREO;
+ c->channels = av_get_channel_layout_nb_channels(c->channel_layout);
+ #else
+- av_channel_layout_copy(&c->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO);
++ AVChannelLayout layout = AV_CHANNEL_LAYOUT_STEREO;
++ av_channel_layout_copy(&c->ch_layout, &layout);
+ #endif
+
+ //deprecated on ffmpeg 4
diff --git a/academic/openboard/openboard.SlackBuild b/academic/openboard/openboard.SlackBuild
index 0e3b98291868..20c00e7ef33f 100644
--- a/academic/openboard/openboard.SlackBuild
+++ b/academic/openboard/openboard.SlackBuild
@@ -28,7 +28,7 @@ PRGNAM=openboard
SRCNAM=OpenBoard
VERSION=${VERSION:-1.6.4}
SRCVER=$(echo $VERSION | tr _ -)
-BUILD=${BUILD:-1}
+BUILD=${BUILD:-2}
TAG=${TAG:-_SBo}
PKGTYPE=${PKGTYPE:-tgz}
@@ -90,6 +90,9 @@ sed -i "s|QuaZip-Qt5-1.1|QuaZip-Qt5-$QUAZIPVER|g" OpenBoard.pro plugins/cffadapt
# Patch to run in a window
patch -p1 < $CWD/run-in-a-window.patch
+# Patch for newer ffmpeg
+patch -p1 < $CWD/31755fe30cf.patch
+
qmake-qt5 OpenBoard.pro -spec linux-g++
make