diff --git a/.github/workflows/_meta_mac_portable.yaml b/.github/workflows/_meta_mac_portable.yaml index d1e2c80695d..7314b75305e 100644 --- a/.github/workflows/_meta_mac_portable.yaml +++ b/.github/workflows/_meta_mac_portable.yaml @@ -20,9 +20,9 @@ jobs: strategy: fail-fast: true matrix: - # Currently, macOS 12 is x86 exclusive and macOS 14 is arm exclusive and we have no other way to specify arch + # Currently, macOS 13 is x86 exclusive and macOS 14 is arm exclusive and we have no other way to specify arch os: - - name: macos-12 + - name: macos-13 arch: x86_64 - name: macos-14 arch: arm64 diff --git a/builder/variants/defaults-mac.sh b/builder/variants/defaults-mac.sh index f171004576a..726ed5a6a3b 100755 --- a/builder/variants/defaults-mac.sh +++ b/builder/variants/defaults-mac.sh @@ -20,3 +20,4 @@ export PKG_CONFIG_LIBDIR="/usr/lib/pkgconfig:/opt/homebrew/Library/Homebrew/os/m export CMAKE_PREFIX_PATH=""$FFBUILD_PREFIX"" export PKG_CONFIG_PATH=""$FFBUILD_PREFIX"/lib/pkgconfig" export RANLIB="/usr/bin/ranlib" +export MACOSX_DEPLOYMENT_TARGET="12.0" diff --git a/debian/patches/0051-add-coreimage-based-vf-transpose-vt-filter.patch b/debian/patches/0051-add-coreimage-based-vf-transpose-vt-filter.patch index 987bf05c300..489c869cd47 100644 --- a/debian/patches/0051-add-coreimage-based-vf-transpose-vt-filter.patch +++ b/debian/patches/0051-add-coreimage-based-vf-transpose-vt-filter.patch @@ -305,8 +305,9 @@ Index: FFmpeg/libavfilter/vf_transpose_vt.m =================================================================== --- /dev/null +++ FFmpeg/libavfilter/vf_transpose_vt.m -@@ -0,0 +1,265 @@ +@@ -0,0 +1,381 @@ +/* ++ * Copyright (c) 2023 Zhao Zhili + * Copyright (c) 2024 Gnattu OC + * + * This file is part of FFmpeg. @@ -327,17 +328,31 @@ Index: FFmpeg/libavfilter/vf_transpose_vt.m + */ + +#include ++#include + +#include "libavutil/hwcontext.h" +#include "libavutil/opt.h" ++#include "libavutil/objc.h" +#include "internal.h" +#include "transpose.h" +#include "video.h" + ++// Declaration for SDKs not having VTPixelRotationSession ++#if (TARGET_OS_OSX && (!defined(__MAC_13_0))) || \ ++ (TARGET_OS_IOS && (!defined(__IPHONE_16_0))) || \ ++ (TARGET_OS_TV && (!defined(__TVOS_16_0))) ++ #define LEGACY_VT_SDK ++#endif ++ ++#ifdef LEGACY_VT_SDK ++typedef void* VTPixelRotationSessionRef; ++#endif ++ +typedef struct TransposeVtContext { + AVClass *class; + CIContext *ci_ctx; + CGImagePropertyOrientation orientation; ++ VTPixelRotationSessionRef session; + + int dir; + int passthrough; @@ -346,10 +361,28 @@ Index: FFmpeg/libavfilter/vf_transpose_vt.m +static av_cold int transpose_vt_init(AVFilterContext *avctx) +{ + TransposeVtContext *s = avctx->priv; -+ s->ci_ctx = CFBridgingRetain([CIContext context]); -+ if (!s->ci_ctx) { -+ av_log(avctx, AV_LOG_ERROR, "CoreImage Context create failed\n"); -+ return AVERROR_EXTERNAL; ++#ifndef LEGACY_VT_SDK ++ if (@available(macOS 13.0, iOS 16, *)) { ++ int ret; ++ ++ ret = VTPixelRotationSessionCreate(kCFAllocatorDefault, &s->session); ++ if (ret != noErr) { ++ av_log(avctx, AV_LOG_ERROR, "Rotation session create failed, %d\n", ret); ++ return AVERROR_EXTERNAL; ++ } else { ++ av_log(avctx, AV_LOG_DEBUG, "VT Rotation session created\n"); ++ } ++ } ++ else ++#endif ++ { ++ s->ci_ctx = CFBridgingRetain([CIContext context]); ++ if (!s->ci_ctx) { ++ av_log(avctx, AV_LOG_ERROR, "CoreImage Context create failed\n"); ++ return AVERROR_EXTERNAL; ++ } else { ++ av_log(avctx, AV_LOG_DEBUG, "CoreImage Context created\n"); ++ } + } + + return 0; @@ -362,6 +395,15 @@ Index: FFmpeg/libavfilter/vf_transpose_vt.m + CFRelease(s->ci_ctx); + s->ci_ctx = NULL; + } ++#ifndef LEGACY_VT_SDK ++ if (@available(macOS 13.0, iOS 16, *)) { ++ if (s->session) { ++ VTPixelRotationSessionInvalidate(s->session); ++ CFRelease(s->session); ++ s->session = NULL; ++ } ++ } ++#endif +} + +static int transpose_vt_filter_frame(AVFilterLink *link, AVFrame *in) @@ -373,8 +415,6 @@ Index: FFmpeg/libavfilter/vf_transpose_vt.m + CVPixelBufferRef src; + CVPixelBufferRef dst; + AVFrame *out; -+ CIImage *source_image = NULL; -+ CIImage *transposed_image = NULL; + + if (s->passthrough) + return ff_filter_frame(outlink, in); @@ -391,19 +431,33 @@ Index: FFmpeg/libavfilter/vf_transpose_vt.m + + src = (CVPixelBufferRef)in->data[3]; + dst = (CVPixelBufferRef)out->data[3]; -+ -+ source_image = CFBridgingRetain([CIImage imageWithCVPixelBuffer: src]); -+ transposed_image = CFBridgingRetain([source_image imageByApplyingCGOrientation: s->orientation]); -+ if (!transposed_image) { -+ CFRelease(source_image); -+ av_log(ctx, AV_LOG_ERROR, "transpose image failed, %d\n", ret); -+ ret = AVERROR_EXTERNAL; -+ goto fail; ++#ifndef LEGACY_VT_SDK ++ if (@available(macOS 13.0, iOS 16, *)) { ++ ret = VTPixelRotationSessionRotateImage(s->session, src, dst); ++ if (ret != noErr) { ++ av_log(ctx, AV_LOG_ERROR, "transfer image failed, %d\n", ret); ++ ret = AVERROR_EXTERNAL; ++ goto fail; ++ } ++ } ++ else ++#endif ++ { ++ @autoreleasepool { ++ CIImage *source_image = NULL; ++ CIImage *transposed_image = NULL; ++ source_image = [CIImage imageWithCVPixelBuffer:src]; ++ transposed_image = [source_image imageByApplyingCGOrientation:s->orientation]; ++ if (!transposed_image) { ++ ff_objc_release(&source_image); ++ av_log(ctx, AV_LOG_ERROR, "transpose image failed, %d\n", ret); ++ ret = AVERROR_EXTERNAL; ++ goto fail; ++ } ++ CVBufferPropagateAttachments(src, dst); ++ [(__bridge CIContext *) s->ci_ctx render:transposed_image toCVPixelBuffer:dst]; ++ } + } -+ [(__bridge CIContext*)s->ci_ctx render: (__bridge CIImage*)transposed_image toCVPixelBuffer: dst]; -+ CFRelease(source_image); -+ CFRelease(transposed_image); -+ CVBufferPropagateAttachments(src, dst); + + av_frame_free(&in); + @@ -470,35 +524,97 @@ Index: FFmpeg/libavfilter/vf_transpose_vt.m + + s->passthrough = TRANSPOSE_PT_TYPE_NONE; + -+ switch (s->dir) { -+ case TRANSPOSE_CCLOCK_FLIP: -+ s->orientation = kCGImagePropertyOrientationLeftMirrored; -+ swap_w_h = 1; -+ break; -+ case TRANSPOSE_CCLOCK: -+ s->orientation = kCGImagePropertyOrientationLeft; -+ swap_w_h = 1; -+ break; -+ case TRANSPOSE_CLOCK: -+ s->orientation = kCGImagePropertyOrientationRight; -+ swap_w_h = 1; -+ break; -+ case TRANSPOSE_CLOCK_FLIP: -+ s->orientation = kCGImagePropertyOrientationRightMirrored; -+ swap_w_h = 1; -+ break; -+ case TRANSPOSE_REVERSAL: -+ s->orientation = kCGImagePropertyOrientationDown; -+ break; -+ case TRANSPOSE_HFLIP: -+ s->orientation = kCGImagePropertyOrientationUpMirrored; -+ break; -+ case TRANSPOSE_VFLIP: -+ s->orientation = kCGImagePropertyOrientationDownMirrored; -+ break; -+ default: -+ av_log(avctx, AV_LOG_ERROR, "Failed to set direction to %d\n", s->dir); -+ return AVERROR(EINVAL); ++#ifndef LEGACY_VT_SDK ++ if (@available(macOS 13.0, iOS 16, *)) { ++ CFStringRef rotation = kVTRotation_0; ++ CFBooleanRef vflip = kCFBooleanFalse; ++ CFBooleanRef hflip = kCFBooleanFalse; ++ ++ switch (s->dir) { ++ case TRANSPOSE_CCLOCK_FLIP: ++ rotation = kVTRotation_CCW90; ++ vflip = kCFBooleanTrue; ++ swap_w_h = 1; ++ break; ++ case TRANSPOSE_CCLOCK: ++ rotation = kVTRotation_CCW90; ++ swap_w_h = 1; ++ break; ++ case TRANSPOSE_CLOCK: ++ rotation = kVTRotation_CW90; ++ swap_w_h = 1; ++ break; ++ case TRANSPOSE_CLOCK_FLIP: ++ rotation = kVTRotation_CW90; ++ vflip = kCFBooleanTrue; ++ swap_w_h = 1; ++ break; ++ case TRANSPOSE_REVERSAL: ++ rotation = kVTRotation_180; ++ break; ++ case TRANSPOSE_HFLIP: ++ hflip = kCFBooleanTrue; ++ break; ++ case TRANSPOSE_VFLIP: ++ vflip = kCFBooleanTrue; ++ break; ++ default: ++ av_log(avctx, AV_LOG_ERROR, "Failed to set direction to %d\n", s->dir); ++ return AVERROR(EINVAL); ++ } ++ ++ err = VTSessionSetProperty(s->session, kVTPixelRotationPropertyKey_Rotation, ++ rotation); ++ if (err != noErr) { ++ av_log(avctx, AV_LOG_ERROR, "Set rotation property failed, %d\n", err); ++ return AVERROR_EXTERNAL; ++ } ++ err = VTSessionSetProperty(s->session, kVTPixelRotationPropertyKey_FlipVerticalOrientation, ++ vflip); ++ if (err != noErr) { ++ av_log(avctx, AV_LOG_ERROR, "Set vertical flip property failed, %d\n", err); ++ return AVERROR_EXTERNAL; ++ } ++ err = VTSessionSetProperty(s->session, kVTPixelRotationPropertyKey_FlipHorizontalOrientation, ++ hflip); ++ if (err != noErr) { ++ av_log(avctx, AV_LOG_ERROR, "Set horizontal flip property failed, %d\n", err); ++ return AVERROR_EXTERNAL; ++ } ++ } ++ else ++#endif ++ { ++ switch (s->dir) { ++ case TRANSPOSE_CCLOCK_FLIP: ++ s->orientation = kCGImagePropertyOrientationLeftMirrored; ++ swap_w_h = 1; ++ break; ++ case TRANSPOSE_CCLOCK: ++ s->orientation = kCGImagePropertyOrientationLeft; ++ swap_w_h = 1; ++ break; ++ case TRANSPOSE_CLOCK: ++ s->orientation = kCGImagePropertyOrientationRight; ++ swap_w_h = 1; ++ break; ++ case TRANSPOSE_CLOCK_FLIP: ++ s->orientation = kCGImagePropertyOrientationRightMirrored; ++ swap_w_h = 1; ++ break; ++ case TRANSPOSE_REVERSAL: ++ s->orientation = kCGImagePropertyOrientationDown; ++ break; ++ case TRANSPOSE_HFLIP: ++ s->orientation = kCGImagePropertyOrientationUpMirrored; ++ break; ++ case TRANSPOSE_VFLIP: ++ s->orientation = kCGImagePropertyOrientationDownMirrored; ++ break; ++ default: ++ av_log(avctx, AV_LOG_ERROR, "Failed to set direction to %d\n", s->dir); ++ return AVERROR(EINVAL); ++ } + } + + if (!swap_w_h)