diff --git a/multimedia/olive/Makefile b/multimedia/olive/Makefile index 6098406b3356..632918e153fa 100644 --- a/multimedia/olive/Makefile +++ b/multimedia/olive/Makefile @@ -1,51 +1,49 @@ PORTNAME= olive DISTVERSION= 0.2.0 DISTVERSIONSUFFIX= -nightly PORTREVISION= 3 CATEGORIES= multimedia PKGNAMESUFFIX= -video-editor PATCH_SITES= https://github.com/${GH_ACCOUNT}/${GH_PROJECT}/commit/ PATCHFILES= 311eeb72944f93f873d1cd1784ee2bf423e1e7c2.patch:-p1 # https://github.com/olive-editor/olive/pull/2294, OpenColorIO 2.3 compatibility MAINTAINER= yuri@FreeBSD.org COMMENT= Non-linear video editor WWW= https://olivevideoeditor.org/ \ https://github.com/olive-editor/olive -BROKEN= Does not build with ffmpeg > 6 - LICENSE= GPLv3 LICENSE_FILE= ${WRKSRC}/LICENSE BROKEN_armv7= compilation fails: error: unknown type name '__m128' BROKEN_i386= compilation fails, see https://github.com/olive-editor/olive/issues/2364 BROKEN_powerpc= compilation fails, see https://github.com/olive-editor/olive/issues/2364 BUILD_DEPENDS= frei0r>0:graphics/frei0r LIB_DEPENDS= libavcodec.so:multimedia/ffmpeg \ libImath.so:math/Imath \ libOpenColorIO.so:graphics/opencolorio \ libOpenEXR.so:graphics/openexr \ libOpenImageIO.so:graphics/openimageio \ libportaudio.so:audio/portaudio RUN_DEPENDS= frei0r>0:graphics/frei0r # libopentimelineio.so:multimedia/opentimelineio USES= cmake compiler:c++17-lang desktop-file-utils gl pkgconfig qt:5 shared-mime-info USE_QT= concurrent core dbus gui multimedia network opengl svg widgets x11extras \ buildtools:build linguisttools:build qmake:build testlib:build USE_GL= gl USE_GITHUB= yes GH_ACCOUNT= olive-editor GH_TUPLE= olive-editor:core:2777928:core/ext/core \ KDAB:KDDockWidgets:8d2d0a5:KDDockWidgets/ext/KDDockWidgets CXXFLAGS_i386= -msse -msse2 PORTSCOUT= limit:^.*[1-9]\..* # prevent tags like 20181223 CONFLICTS_BUILD= opentimelineio # fails to build with the opentimelineio optional dependency, see https://github.com/olive-editor/olive/issues/2201 .include diff --git a/multimedia/olive/files/patch-app_audio_audioprocessor.cpp b/multimedia/olive/files/patch-app_audio_audioprocessor.cpp new file mode 100644 index 000000000000..4c0acc8728ba --- /dev/null +++ b/multimedia/olive/files/patch-app_audio_audioprocessor.cpp @@ -0,0 +1,15 @@ +--- app/audio/audioprocessor.cpp.orig 2026-02-28 23:14:00 UTC ++++ app/audio/audioprocessor.cpp +@@ -169,8 +169,12 @@ bool AudioProcessor::Open(const AudioParams &from, con + if (in_frame_) { + in_frame_->sample_rate = from.sample_rate(); + in_frame_->format = from_fmt_; ++#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) ++ av_channel_layout_from_mask(&in_frame_->ch_layout, from.channel_layout()); ++#else + in_frame_->channel_layout = from.channel_layout(); + in_frame_->channels = from.channel_count(); ++#endif + in_frame_->pts = 0; + } else { + qCritical() << "Failed to allocate input frame"; diff --git a/multimedia/olive/files/patch-app_codec_ffmpeg_ffmpegdecoder.cpp b/multimedia/olive/files/patch-app_codec_ffmpeg_ffmpegdecoder.cpp new file mode 100644 index 000000000000..fae98a10ad3c --- /dev/null +++ b/multimedia/olive/files/patch-app_codec_ffmpeg_ffmpegdecoder.cpp @@ -0,0 +1,123 @@ +--- app/codec/ffmpeg/ffmpegdecoder.cpp.orig 2024-12-04 17:13:33 UTC ++++ app/codec/ffmpeg/ffmpegdecoder.cpp +@@ -355,8 +355,15 @@ FootageDescription FFmpegDecoder::Probe(const QString + // Read first frame and retrieve some metadata + if (instance.GetFrame(pkt, frame) >= 0) { + // Check if video is interlaced and what field dominance it has if so ++#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(58, 0, 100) ++ int interlaced = (frame->flags & AV_FRAME_FLAG_INTERLACED); ++ int top_field_first = (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST); ++ if (interlaced) { ++ if (top_field_first) { ++#else + if (frame->interlaced_frame) { + if (frame->top_field_first) { ++#endif + interlacing = VideoParams::kInterlacedTopFirst; + } else { + interlacing = VideoParams::kInterlacedBottomFirst; +@@ -439,10 +446,30 @@ FootageDescription FFmpegDecoder::Probe(const QString + } else if (avstream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + + // Create an audio stream object ++#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) ++ uint64_t channel_layout; ++ if (avstream->codecpar->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) { ++ AVChannelLayout ch_layout = AV_CHANNEL_LAYOUT_MASK(0, 0); ++ av_channel_layout_copy(&ch_layout, &avstream->codecpar->ch_layout); ++ if (ch_layout.order == AV_CHANNEL_ORDER_NATIVE && ch_layout.u.mask) { ++ channel_layout = ch_layout.u.mask; ++ } else { ++ av_channel_layout_default(&ch_layout, avstream->codecpar->ch_layout.nb_channels); ++ channel_layout = ch_layout.u.mask; ++ } ++ av_channel_layout_uninit(&ch_layout); ++ } else { ++ AVChannelLayout ch_layout = AV_CHANNEL_LAYOUT_MASK(0, 0); ++ av_channel_layout_default(&ch_layout, avstream->codecpar->ch_layout.nb_channels); ++ channel_layout = ch_layout.u.mask; ++ av_channel_layout_uninit(&ch_layout); ++ } ++#else + uint64_t channel_layout = avstream->codecpar->channel_layout; + if (!channel_layout) { + channel_layout = static_cast(av_get_default_channel_layout(avstream->codecpar->channels)); + } ++#endif + + if (avstream->duration == AV_NOPTS_VALUE || duration_guessed_from_bitrate) { + // Loop through stream until we get the whole duration +@@ -558,6 +585,29 @@ bool FFmpegDecoder::ConformAudioInternal(const QVector + } + + // Create resampling context ++#if LIBSWRESAMPLE_VERSION_INT >= AV_VERSION_INT(4, 5, 100) ++ AVChannelLayout out_ch_layout = AV_CHANNEL_LAYOUT_MASK(0, 0); ++ AVChannelLayout in_ch_layout = AV_CHANNEL_LAYOUT_MASK(0, 0); ++ av_channel_layout_from_mask(&out_ch_layout, params.channel_layout()); ++ av_channel_layout_from_mask(&in_ch_layout, channel_layout); ++ ++ SwrContext* resampler = nullptr; ++ int swr_ret = swr_alloc_set_opts2(&resampler, ++ &out_ch_layout, ++ FFmpegUtils::GetFFmpegSampleFormat(params.format()), ++ params.sample_rate(), ++ &in_ch_layout, ++ static_cast(instance_.avstream()->codecpar->format), ++ instance_.avstream()->codecpar->sample_rate, ++ 0, ++ nullptr); ++ av_channel_layout_uninit(&out_ch_layout); ++ av_channel_layout_uninit(&in_ch_layout); ++ ++ if (swr_ret < 0) { ++ return false; ++ } ++#else + SwrContext* resampler = swr_alloc_set_opts(nullptr, + params.channel_layout(), + FFmpegUtils::GetFFmpegSampleFormat(params.format()), +@@ -567,6 +617,7 @@ bool FFmpegDecoder::ConformAudioInternal(const QVector + instance_.avstream()->codecpar->sample_rate, + 0, + nullptr); ++#endif + + swr_init(resampler); + +@@ -691,11 +742,35 @@ uint64_t FFmpegDecoder::ValidateChannelLayout(AVStream + + uint64_t FFmpegDecoder::ValidateChannelLayout(AVStream* stream) + { ++#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) ++ if (stream->codecpar->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) { ++ AVChannelLayout ch_layout = AV_CHANNEL_LAYOUT_MASK(0, 0); ++ av_channel_layout_copy(&ch_layout, &stream->codecpar->ch_layout); ++ uint64_t mask = 0; ++ if (ch_layout.order == AV_CHANNEL_ORDER_NATIVE && ch_layout.u.mask) { ++ mask = ch_layout.u.mask; ++ } else { ++ AVChannelLayout default_layout = AV_CHANNEL_LAYOUT_MASK(0, 0); ++ av_channel_layout_default(&default_layout, stream->codecpar->ch_layout.nb_channels); ++ mask = default_layout.u.mask; ++ av_channel_layout_uninit(&default_layout); ++ } ++ av_channel_layout_uninit(&ch_layout); ++ return mask; ++ } ++ ++ AVChannelLayout ch_layout = AV_CHANNEL_LAYOUT_MASK(0, 0); ++ av_channel_layout_default(&ch_layout, stream->codecpar->ch_layout.nb_channels); ++ uint64_t mask = ch_layout.u.mask; ++ av_channel_layout_uninit(&ch_layout); ++ return mask; ++#else + if (stream->codecpar->channel_layout) { + return stream->codecpar->channel_layout; + } + + return av_get_default_channel_layout(stream->codecpar->channels); ++#endif + } + + const char *FFmpegDecoder::GetInterlacingModeInFFmpeg(VideoParams::Interlacing interlacing) diff --git a/multimedia/olive/files/patch-app_codec_ffmpeg_ffmpegencoder.cpp b/multimedia/olive/files/patch-app_codec_ffmpeg_ffmpegencoder.cpp new file mode 100644 index 000000000000..943c59accca8 --- /dev/null +++ b/multimedia/olive/files/patch-app_codec_ffmpeg_ffmpegencoder.cpp @@ -0,0 +1,108 @@ +--- app/codec/ffmpeg/ffmpegencoder.cpp.orig 2024-12-04 17:13:33 UTC ++++ app/codec/ffmpeg/ffmpegencoder.cpp +@@ -334,7 +334,11 @@ bool FFmpegEncoder::WriteAudioData(const AudioParams & + int output_sample_count = input_sample_count ? swr_get_out_samples(audio_resample_ctx_, input_sample_count) : 102400; + uint8_t** output_data = nullptr; + int output_linesize; ++#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) ++ av_samples_alloc_array_and_samples(&output_data, &output_linesize, audio_stream_->codecpar->ch_layout.nb_channels, ++#else + av_samples_alloc_array_and_samples(&output_data, &output_linesize, audio_stream_->codecpar->channels, ++#endif + output_sample_count, static_cast(audio_stream_->codecpar->format), 0); + + // Perform conversion +@@ -349,7 +353,11 @@ bool FFmpegEncoder::WriteAudioData(const AudioParams & + + av_samples_copy(audio_frame_->data, output_data, audio_frame_offset_, i, + copy_length, ++#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) ++ audio_frame_->ch_layout.nb_channels, static_cast(audio_frame_->format)); ++#else + audio_frame_->channels, static_cast(audio_frame_->format)); ++#endif + + audio_frame_offset_ += copy_length; + i += copy_length; +@@ -690,8 +698,12 @@ bool FFmpegEncoder::InitializeStream(AVMediaType type, + + // Assume audio stream + codec_ctx->sample_rate = params().audio_params().sample_rate(); ++#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) ++ av_channel_layout_from_mask(&codec_ctx->ch_layout, params().audio_params().channel_layout()); ++#else + codec_ctx->channel_layout = params().audio_params().channel_layout(); + codec_ctx->channels = av_get_channel_layout_nb_channels(codec_ctx->channel_layout); ++#endif + codec_ctx->sample_fmt = FFmpegUtils::GetFFmpegSampleFormat(params().audio_params().format()); + codec_ctx->time_base = {1, codec_ctx->sample_rate}; + +@@ -787,12 +799,19 @@ void FFmpegEncoder::FlushEncoders() + } + + if (fmt_ctx_) { ++#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(59, 0, 100) ++ // AVFMT_ALLOW_FLUSH removed in ffmpeg 7+, always allow flush now ++ int r = av_interleaved_write_frame(fmt_ctx_, nullptr); ++#else + if (fmt_ctx_->oformat->flags & AVFMT_ALLOW_FLUSH) { + int r = av_interleaved_write_frame(fmt_ctx_, nullptr); ++#endif + if (r < 0) { + FFmpegError(tr("Failed to write interleaved packet"), r); + } ++#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(59, 0, 100) + } ++#endif + } + } + +@@ -829,6 +848,28 @@ bool FFmpegEncoder::InitializeResampleContext(const Au + } + + // Create resample context ++#if LIBSWRESAMPLE_VERSION_INT >= AV_VERSION_INT(4, 5, 100) ++ AVChannelLayout out_ch_layout = AV_CHANNEL_LAYOUT_MASK(0, 0); ++ AVChannelLayout in_ch_layout = AV_CHANNEL_LAYOUT_MASK(0, 0); ++ av_channel_layout_from_mask(&out_ch_layout, audio_codec_ctx_->ch_layout.u.mask ? audio_codec_ctx_->ch_layout.u.mask : AV_CH_LAYOUT_STEREO); ++ av_channel_layout_from_mask(&in_ch_layout, audio.channel_layout()); ++ ++ int ret = swr_alloc_set_opts2(&audio_resample_ctx_, ++ &out_ch_layout, ++ audio_codec_ctx_->sample_fmt, ++ audio_codec_ctx_->sample_rate, ++ &in_ch_layout, ++ FFmpegUtils::GetFFmpegSampleFormat(audio.format()), ++ audio.sample_rate(), ++ 0, ++ nullptr); ++ av_channel_layout_uninit(&out_ch_layout); ++ av_channel_layout_uninit(&in_ch_layout); ++ ++ if (ret < 0) { ++ return false; ++ } ++#else + audio_resample_ctx_ = swr_alloc_set_opts(nullptr, + static_cast(audio_codec_ctx_->channel_layout), + audio_codec_ctx_->sample_fmt, +@@ -838,6 +879,7 @@ bool FFmpegEncoder::InitializeResampleContext(const Au + audio.sample_rate(), + 0, + nullptr); ++#endif + if (!audio_resample_ctx_) { + return false; + } +@@ -865,7 +907,11 @@ bool FFmpegEncoder::InitializeResampleContext(const Au + return false; + } + ++#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) ++ av_channel_layout_copy(&audio_frame_->ch_layout, &audio_codec_ctx_->ch_layout); ++#else + audio_frame_->channel_layout = audio_codec_ctx_->channel_layout; ++#endif + audio_frame_->format = audio_codec_ctx_->sample_fmt; + audio_frame_->nb_samples = audio_max_samples_; + diff --git a/multimedia/olive/files/patch-app_codec_oiio_oiiodecoder.cpp b/multimedia/olive/files/patch-app_codec_oiio_oiiodecoder.cpp new file mode 100644 index 000000000000..cf080193683b --- /dev/null +++ b/multimedia/olive/files/patch-app_codec_oiio_oiiodecoder.cpp @@ -0,0 +1,23 @@ +--- app/codec/oiio/oiiodecoder.cpp.orig 2026-02-28 23:20:04 UTC ++++ app/codec/oiio/oiiodecoder.cpp +@@ -134,10 +134,20 @@ TexturePtr OIIODecoder::RetrieveVideoInternal(const Re + + if (p.divider == 1) { + // Just upload straight to the buffer ++#if OIIO_VERSION >= OIIO_MAKE_VERSION(3, 0, 0) ++ // OpenImageIO 3.0+ requires subimage, miplevel, chbegin, chend parameters ++ image_->read_image(0, 0, 0, image_->spec().nchannels, oiio_pix_fmt_, buffer_.data(), OIIO::AutoStride, buffer_.linesize_bytes()); ++#else + image_->read_image(oiio_pix_fmt_, buffer_.data(), OIIO::AutoStride, buffer_.linesize_bytes()); ++#endif + } else { + OIIO::ImageBuf buf(image_->spec()); ++#if OIIO_VERSION >= OIIO_MAKE_VERSION(3, 0, 0) ++ // OpenImageIO 3.0+ requires subimage, miplevel, chbegin, chend parameters ++ image_->read_image(0, 0, 0, image_->spec().nchannels, image_->spec().format, buf.localpixels(), buf.pixel_stride(), buf.scanline_stride(), buf.z_stride()); ++#else + image_->read_image(image_->spec().format, buf.localpixels(), buf.pixel_stride(), buf.scanline_stride(), buf.z_stride()); ++#endif + + // Roughly downsample image for divider (for some reason OIIO::ImageBufAlgo::resample failed here) + int px_sz = vp.GetBytesPerPixel(); diff --git a/multimedia/olive/files/patch-ext_core_src_render_audioparams.cpp b/multimedia/olive/files/patch-ext_core_src_render_audioparams.cpp new file mode 100644 index 000000000000..013260a0ff3f --- /dev/null +++ b/multimedia/olive/files/patch-ext_core_src_render_audioparams.cpp @@ -0,0 +1,22 @@ +--- ext/core/src/render/audioparams.cpp.orig 2026-02-28 23:05:00 UTC ++++ ext/core/src/render/audioparams.cpp +@@ -159,7 +159,19 @@ void AudioParams::calculate_channel_count() + + void AudioParams::calculate_channel_count() + { ++#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) ++ // ffmpeg 5.1+ uses new channel layout API ++ AVChannelLayout ch_layout = AV_CHANNEL_LAYOUT_MASK(0, 0); ++ if (channel_layout() > 0) { ++ av_channel_layout_from_mask(&ch_layout, channel_layout()); ++ channel_count_ = ch_layout.nb_channels; ++ av_channel_layout_uninit(&ch_layout); ++ } else { ++ channel_count_ = 0; ++ } ++#else + channel_count_ = av_get_channel_layout_nb_channels(channel_layout()); ++#endif + } + + }