CI: Fix build errors with Xcode 14.3 and platform SDK 13.3

Xcode 14.3 and the macOS 13.3 platform SDK introduced a few breaking
changes:

* Updated AppleClang emits warnings about unqualified std cast calls
  when using C++ - as `move` is too broad a word, developers are to use
  `std::move` to make this explicit. Alas this is exactly what `json11`
  uses and because that library is archived, there is no possibility
  of an upstream update.

* Apple guarded calls to old screen capture APIs as "available but
  deprecated", but seems to have chosen the wrong lower version
  boundary: The calls are flagged as being available for macOS 13 and
  macOS 14 only.

  To fix this, the existing macOS platform SDK header is replaced by a
  local copy that uses macOS 11 as the lower boundary (the oldest macOS
  version supported by obs-studio anyway)
This commit is contained in:
PatTheMav 2023-04-04 15:15:51 +02:00 committed by Ryan Foster
parent 6e07b86729
commit ee3c2d0e8a
5 changed files with 369 additions and 30 deletions

View file

@ -15,3 +15,7 @@ target_link_libraries(obs-studio PRIVATE ${APPKIT} ${AVFOUNDATION} ${APPLICATION
target_compile_options(obs-studio PRIVATE -Wno-error=float-conversion -Wno-error=implicit-int-conversion
-Wno-error=shorten-64-to-32)
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 14.0.3)
target_compile_options(obs-studio PRIVATE -Wno-error=unqualified-std-cast-call)
endif()

View file

@ -308,34 +308,15 @@ MacPermissionStatus CheckPermissionWithPrompt(MacPermissionType type,
break;
}
case kScreenCapture: {
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 110000
if (@available(macOS 11.0, *)) {
permissionResponse = (CGPreflightScreenCaptureAccess()
permissionResponse = (CGPreflightScreenCaptureAccess()
? kPermissionAuthorized
: kPermissionDenied);
if (permissionResponse != kPermissionAuthorized &&
prompt_for_permission) {
permissionResponse = (CGRequestScreenCaptureAccess()
? kPermissionAuthorized
: kPermissionDenied);
if (permissionResponse != kPermissionAuthorized &&
prompt_for_permission) {
permissionResponse =
(CGRequestScreenCaptureAccess()
? kPermissionAuthorized
: kPermissionDenied);
}
} else {
#else
{
#endif
CGDisplayStreamRef stream = CGDisplayStreamCreate(
CGMainDisplayID(), 1, 1,
kCVPixelFormatType_32BGRA, nil, nil);
if (stream) {
permissionResponse = kPermissionAuthorized;
CFRelease(stream);
} else {
permissionResponse = kPermissionDenied;
}
}
blog(LOG_INFO, "[macOS] Permission for screen capture %s.",

View file

@ -0,0 +1,352 @@
/* CoreGraphics - CGDisplayStream.h
Copyright (c) 2011-2013 Apple Inc.
All rights reserved. */
#ifndef CGDISPLAYSTREAM_H_
#define CGDISPLAYSTREAM_H_
#include <CoreFoundation/CoreFoundation.h>
#include <CoreFoundation/CFAvailability.h>
#include <stdint.h>
#include <dispatch/dispatch.h>
#include <CoreGraphics/CGDirectDisplay.h>
CF_IMPLICIT_BRIDGING_ENABLED
CF_ASSUME_NONNULL_BEGIN
#ifdef __BLOCKS__
/*!
@typedef CGDisplayStreamRef
@abstract An opaque reference to a CGDisplayStream object
@discussion A CGDisplayStream provides a streaming API for capturing display updates in a realtime manner. It can also provide
scaling and color space conversion services, as well as allow capturing sub regions of the display. Callbacks can be targetted
at either a traditional CFRunLoop, or at a dispatch queue.
*/
typedef struct CF_BRIDGED_TYPE(id) CGDisplayStream *CGDisplayStreamRef;
/*!
@typedef CGDisplayStreamUpdateRef
@abstract An opaque reference to a single frame's extra metadata that describes useful frame delta information
@discussion A CGDisplayStreamUpdate encapsulates information about what portions of a frame have changed relative to
a previously delivered frame. This includes regions that were changed in any way, which ones were actually redrawn, and which
regions were merely copied from one place to another. A routine is provided to merge two update refs together in cases
where apps need to coalesce the values because they decided to skip processing for one or more frames.
*/
typedef const struct CF_BRIDGED_TYPE(id)
CGDisplayStreamUpdate *CGDisplayStreamUpdateRef;
/*!
@enum CGDisplayStreamUpdateRectType
@abstract Used to select which array of rectangles to be returned by CGDisplayUpdateGetRects
@const kCGDisplayStreamUpdateRefreshedRects The rectangles that were refreshed on the display, not counting moved rectangles
@const kCGDisplayStreamUpdateMovedRects The rectangles that were simply moved from one part of the display to another
@const kCGDisplayStreamUpdateDirtyRects The union of both refreshed and moved rects
@const kCGDisplayStreamUpdateReducedDirtyRects A possibly simplified (but overstated) array of dirty rectangles
*/
typedef CF_ENUM(int32_t, CGDisplayStreamUpdateRectType) {
kCGDisplayStreamUpdateRefreshedRects,
kCGDisplayStreamUpdateMovedRects,
kCGDisplayStreamUpdateDirtyRects,
kCGDisplayStreamUpdateReducedDirtyRects,
};
/*!
@enum CGDisplayStreamFrameStatus
@abstract Provides information about incoming frame updates
@const kCGDisplayStreamFrameStatusFrameComplete A new frame has been generated by the Window Server for a particular display at time displayTime
@const kCGDisplayStreamFrameStatusFrameIdle The Window Server did not generate a new frame for displayTime
@const kCGDisplayStreamFrameStatusFrameBlank As of displayTime, the display has gone blank
@const kCGDisplayStreamFrameStatusStopped The display stream has stopped and no more calls will be made to the handler until the stream is started.
*/
typedef CF_ENUM(int32_t, CGDisplayStreamFrameStatus) {
kCGDisplayStreamFrameStatusFrameComplete,
kCGDisplayStreamFrameStatusFrameIdle,
kCGDisplayStreamFrameStatusFrameBlank,
kCGDisplayStreamFrameStatusStopped,
};
/*
@callback CGDisplayStreamFrameAvailableHandler
@abstract The block prototype used for new frame delivery by CGDisplayStream objects
@discussion For each frame that is generated by the WindowServer for a particular display, the user provided block is invoked and provides the user with an IOSurfaceRef
that contains the pixel data for the new frame, as well as a CGDisplayStreamUpdateRef that contains all of the metadata associated with that IOSurface.
@param frameSurface The IOSurfaceRef for the current frame. May be NULL in some cases. If you intend to hold on to the IOSurface beyond the lifetime of
the handler call, you must CFRetain() the IOSurface until you are done with it *and* you must call IOSurfaceIncrementUseCount() to let the CGDisplayStream know
that the frame is not ready for re-use. Once you are finished using the IOSurfaceRef you must then call IOSurfaceDecrementUseCount(). If you are maintaing
any kind of external cache of information about the IOSurface (such as a GL texture object), you must keep a CFRetain() on the IOSurface to prevent it from going
away until you remove it from your cache. You can not depend on the set of IOSurfaces being used by the display stream as being static, so you should implement
some kind of age-out behavior for your cache for IOSurfaces that have not been re-used in a while.
@param displayTime The mach_absolute_time() of when the corresponding frame was to be displayed by the WindowServer
@param updateRef The CGDisplayStreamUpdateRef for the current frame. Note: If you want to keep the CGDisplayStreamUpdateRef around beyond the lifetime
of the handler, you must CFRetain() it, as it will be CFRelease()'d by the CGDisplayStream after the handler returns. The updateRef will be NULL in cases
when status is not kCGDisplayStreamFrameStatusFrameComplete.
*/
typedef void (^CGDisplayStreamFrameAvailableHandler)(
CGDisplayStreamFrameStatus status, uint64_t displayTime,
IOSurfaceRef __nullable frameSurface,
CGDisplayStreamUpdateRef __nullable updateRef);
/*!
@function CGDisplayStreamUpdateGetTypeID
@abstract Returns the CF "class" ID for CGDisplayStreamUpdate
@result The CFTypeID of the CGDisplayStreamUpdate class.
*/
CG_EXTERN CFTypeID
CGDisplayStreamUpdateGetTypeID(void) CG_AVAILABLE_BUT_DEPRECATED(
11.0, 14.0,
"There is no direct replacement for this function. Please use ScreenCaptureKit API's SCStreamOutputType instead");
/*!
@function CGDisplayStreamUpdateGetRects
@abstract Returns a pointer to an array of CGRect structs that describe what parts of the frame have changed relative
to the previously delivered frame. This rectangle list encapsulates both the update rectangles and movement rectangles.
@param updateRef The CGDisplayStreamUpdateRef
@param rectCount A pointer to where the count of the number of rectangles in the array is to be returned. Must not be NULL.
@result A pointer to the array of CGRectangles. This array should not be freed by the caller.
*/
CG_EXTERN const CGRect *__nullable CGDisplayStreamUpdateGetRects(
CGDisplayStreamUpdateRef __nullable updateRef,
CGDisplayStreamUpdateRectType rectType, size_t *rectCount)
CG_AVAILABLE_BUT_DEPRECATED(
11.0, 14.0,
"Please use ScreenCaptureKit API's SCStreamFrameInfo with SCStreamFrameInfoContentRect instead");
/*!
@function CGDisplayStreamUpdateCreateMerged
@abstract Merge two CGDisplayUpdateRefs into a new one.
@discussion In cases where the client wishes to drop certain frame updates, this function may be used to merge two
CGDisplayUpdateRefs together. The core bit of functionality here is generating a new set of refresh/move/dirty
rectangle arrays that properly represent the union of the deltas between the two frames. Note that the ordering of
the two refs is important.
@param firstUpdate The first update (in a temporal sense)
@param secondUpdate The second update (in a temporal sense)
@result The new CGDisplayStreamUpdateRef
*/
CG_EXTERN CGDisplayStreamUpdateRef __nullable
CGDisplayStreamUpdateCreateMergedUpdate(
CGDisplayStreamUpdateRef __nullable firstUpdate,
CGDisplayStreamUpdateRef __nullable secondUpdate)
CG_AVAILABLE_BUT_DEPRECATED(
11.0, 14.0,
"There is no direct replacement for this function. Please use ScreenCaptureKit API's SCStreamFrameInfo to replace CGDisplayStreamUpdate");
/*!
@function CGDisplayStreamUpdateGetMovedRectsDelta
@abstract Return the movement dx and dy values for a single update
@param updateRef The CGDisplayStreamUpdateRef
@param dx A pointer to a CGFloat to store the x component of the movement delta
@param dy A pointer to a CGFloat to store the y component of the movement delta
@discussion The delta values describe the offset from the moved rectangles back to the source location.
*/
CG_EXTERN void CGDisplayStreamUpdateGetMovedRectsDelta(
CGDisplayStreamUpdateRef __nullable updateRef, CGFloat *dx, CGFloat *dy)
CG_AVAILABLE_BUT_DEPRECATED(
11.0, 14.0,
"Please use ScreenCaptureKit API's SCStreamFrameInfo with SCStreamFrameInfoContentRect instead");
/*!
@function CGDisplayStreamGetDropCount
@abstract Return how many frames (if any) have been dropped since the last call to the handler.
@param updateRef The CGDisplayStreamUpdateRef
@result The number of dropped frames
@discussion This call is primarily useful for performance measurement to determine if the client is keeping up with
all WindowServer updates.
*/
CG_EXTERN size_t
CGDisplayStreamUpdateGetDropCount(CGDisplayStreamUpdateRef __nullable updateRef)
CG_AVAILABLE_BUT_DEPRECATED(
11.0, 14.0,
"There is no direct replacement for this function. Please use ScreenCaptureKit API's SCStreamFrameInfo to replace CGDisplayStreamUpdate");
/* Optional CGDisplayStream Properties */
/*!
@const kCGDisplayStreamSourceRect
@discussion This may be used to request a subregion of the display to be provided as the source of the display stream. Use
CGRectCreateDictionaryRepresentation to convert from a CGRect to the value used here. Note: The coordinate system for the
source rectangle is specified in display logical coordinates and not in pixels, in order to match the normal convention on
HiDPI displays.
*/
CG_EXTERN const CFStringRef kCGDisplayStreamSourceRect CG_AVAILABLE_BUT_DEPRECATED(
11.0, 14.0,
"Please use ScreenCaptureKit API's SCStreamConfiguration sourceRect property instead"); /* Source rectangle to capture - defaults to entire display */
/*!
@const kCGDisplayStreamDestinationRect
@discussion This may be used to request where within the destination buffer the display updates should be placed. Use
CGRectCreateDictionaryRepresentation to convert from a CGRect to the value used here. Note: The coordinate system for
the destination rectangle is always specified in output pixels to match the fact that the output buffer size is also
specified in terms of pixels.
*/
CG_EXTERN const CFStringRef kCGDisplayStreamDestinationRect CG_AVAILABLE_BUT_DEPRECATED(
11.0, 14.0,
"Please use ScreenCaptureKit API's SCStreamConfiguration destinationRect property instead"); /* Destination rectangle - defaults to entire buffer */
/*!
@const kCGDisplayStreamPreserveAspectRatio
@discussion Enable/disable the work the Window Server will do to preserve the display aspect ratio. By default the Window Server will
assume that it should preserve the original aspect ratio of the source display rect. If the aspect ratio of the source display and
the display stream destination rect are not the same, black borders will be inserted at the top/bottom or right/left sides of the destination
in order to preserve the source aspect ratio.
*/
CG_EXTERN const CFStringRef kCGDisplayStreamPreserveAspectRatio CG_AVAILABLE_BUT_DEPRECATED(
11.0, 14.0,
"Please use ScreenCaptureKit API's SCStreamConfiguration preserveAspectRatio property instead"); /* CFBoolean - defaults to true */
/*!
@const kCGDisplayStreamColorSpace
@discussion Set the desired CGColorSpace of the output frames. By default the color space will be that of the display.
*/
CG_EXTERN const CFStringRef kCGDisplayStreamColorSpace CG_AVAILABLE_BUT_DEPRECATED(
11.0, 14.0,
"Please use ScreenCaptureKit API's SCStreamConfiguration colorSpaceName property instead"); /* Desired output color space (CGColorSpaceRef) - defaults to display color space */
/*!
@const kCGDisplayStreamMinimumFrameTime
@discussion Request that the delta between frame updates be at least as much specified by this value.
*/
CG_EXTERN const CFStringRef kCGDisplayStreamMinimumFrameTime CG_AVAILABLE_BUT_DEPRECATED(
11.0, 14.0,
"Please use ScreenCaptureKit API's SCStreamConfiguration minimumFrameInterval property instead"); /* CFNumber in seconds, defaults to zero. */
/*!
@const kCGDisplayStreamShowCursor
@discussion Controls whether the cursor is embedded within the provided buffers or not.
*/
CG_EXTERN const CFStringRef kCGDisplayStreamShowCursor CG_AVAILABLE_BUT_DEPRECATED(
11.0, 14.0,
"Please use ScreenCaptureKit API's SCStreamConfiguration showsCursor property instead"); /* CFBoolean - defaults to false */
/*!
@const kCGDisplayStreamQueueDepth
@discussion Controls how many frames deep the frame queue will be. Defaults to N.
*/
CG_EXTERN const CFStringRef kCGDisplayStreamQueueDepth CG_AVAILABLE_BUT_DEPRECATED(
11.0, 14.0,
"Please use ScreenCaptureKit API's SCStreamConfiguration queueDepth property instead"); /* Queue depth in frames. Defaults to 3. */
/*!
@const kCGDisplayStreamYCbCrMatrix
@discussion When outputting frames in 420v or 420f format, this key may be used to control which YCbCr matrix is used
The value should be one of the three kCGDisplayStreamYCbCrMatrix values specified below.
*/
CG_EXTERN const CFStringRef kCGDisplayStreamYCbCrMatrix CG_AVAILABLE_BUT_DEPRECATED(
11.0, 14.0,
"Please use ScreenCaptureKit API's SCStreamConfiguration colorMatrix property");
/* Supported YCbCr matrices. Note that these strings have identical values to the equivalent CoreVideo strings. */
CG_EXTERN const CFStringRef kCGDisplayStreamYCbCrMatrix_ITU_R_709_2;
CG_EXTERN const CFStringRef kCGDisplayStreamYCbCrMatrix_ITU_R_601_4;
CG_EXTERN const CFStringRef kCGDisplayStreamYCbCrMatrix_SMPTE_240M_1995;
/*!
@function CGDisplayStreamGetTypeID
@abstract Returns the CF "class" ID for CGDisplayStream
@result The CFTypeID of the CGDisplayStream class.
*/
CG_EXTERN CFTypeID CGDisplayStreamGetTypeID(void) CG_AVAILABLE_BUT_DEPRECATED(
11.0, 14.0,
"There is no direct replacement for this function. Please use ScreenCaptureKit API's SCStream to replace CGDisplayStream");
/*!
@function CGDisplayStreamCreate
@abstract Creates a new CGDisplayStream intended to be used with a CFRunLoop
@discussion This function creates a new CGDisplayStream that is to be used to get a stream of frame updates
from a particular display.
@param display The CGDirectDisplayID to use as the source for generated frames
@param outputWidth The output width (in pixels, not points) of the frames to be generated. Must not be zero.
@param outputHeight The output height (in pixels, not points) of the frames to be generated. Must not be zero.
@param pixelFormat The desired CoreVideo/CoreMedia-style pixel format of the output IOSurfaces. The currently
supported values are:
'BGRA' Packed Little Endian ARGB8888
'l10r' Packed Little Endian ARGB2101010
'420v' 2-plane "video" range YCbCr 4:2:0
'420f' 2-plane "full" range YCbCr 4:2:0
@param properties Any optional properties of the CGDisplayStream
@param handler A block that will be called for frame deliver.
@result The new CGDisplayStream object.
*/
CG_EXTERN CGDisplayStreamRef __nullable CGDisplayStreamCreate(
CGDirectDisplayID display, size_t outputWidth, size_t outputHeight,
int32_t pixelFormat, CFDictionaryRef __nullable properties,
CGDisplayStreamFrameAvailableHandler __nullable handler)
CG_AVAILABLE_BUT_DEPRECATED(
11.0, 14.0,
"Please use ScreenCaptureKit API's initWithFilter:configuration:delegate: instead");
/*!
@function CGDisplayStreamCreateWithDispatchQueue
@abstract Creates a new CGDisplayStream intended to be serviced by a block handler
@discussion This function creates a new CGDisplayStream that is to be used to get a stream of frame updates
from a particular display.
@param display The CGDirectDisplayID to use as the source for generated frames
@param outputWidth The output width (in pixels, not points) of the frames to be generated. Must not be zero.
@param outputHeight The output height (in pixels, not points) of the frames to be generated. Must not be zero.
@param pixelFormat The desired CoreVideo/CoreMedia-style pixel format of the output IOSurfaces
@param properties Any optional properties of the CGDisplayStream
@param queue The dispatch_queue_t that will be used to invoke the callback handler.
@param handler A block that will be called for frame deliver.
@result The new CGDisplayStream object.
*/
CG_EXTERN CGDisplayStreamRef __nullable CGDisplayStreamCreateWithDispatchQueue(
CGDirectDisplayID display, size_t outputWidth, size_t outputHeight,
int32_t pixelFormat, CFDictionaryRef __nullable properties,
dispatch_queue_t queue,
CGDisplayStreamFrameAvailableHandler __nullable handler)
CG_AVAILABLE_BUT_DEPRECATED(
11.0, 14.0,
"Please use ScreenCaptureKit API's initWithFilter:configuration:delegate: instead");
/*!
@function CGDisplayStreamStart
@abstract Begin delivering frame updates to the handler block.
@param displayStream to be started
@result kCGErrorSuccess If the display stream was started, otherwise an error.
*/
CG_EXTERN CGError
CGDisplayStreamStart(CGDisplayStreamRef cg_nullable displayStream)
CG_AVAILABLE_BUT_DEPRECATED(
11.0, 14.0,
"Please use ScreenCaptureKit API's startCaptureWithCompletionHandler: to start a stream instead");
/*!
@function CGDisplayStreamStop
@abstract End delivery of frame updates to the handler block.
@param displayStream to be stopped
@result kCGErrorSuccess If the display stream was stopped, otherwise an error.
@discussion After this call returns, the CGDisplayStream callback function will eventually be called with a
status of kCGDisplayStreamFrameStatusStopped. After that point it is safe to release the CGDisplayStream.
It is safe to call this function from within the handler block, but the previous caveat still applies.
*/
CG_EXTERN CGError
CGDisplayStreamStop(CGDisplayStreamRef cg_nullable displayStream)
CG_AVAILABLE_BUT_DEPRECATED(
11.0, 14.0,
"Please use ScreenCaptureKit API's stopCaptureWithCompletionHandler: to stop a stream instead");
/*!
@function CGDisplayStreamGetRunLoopSource
@abstract Return the singleton CFRunLoopSourceRef for a CGDisplayStream.
@param displayStream The CGDisplayStream object
@result The CFRunLoopSource for this displayStream. Note: This function will return NULL if the
display stream was created via CGDisplayStreamCreateWithDispatchQueue().
*/
CG_EXTERN CFRunLoopSourceRef __nullable
CGDisplayStreamGetRunLoopSource(CGDisplayStreamRef cg_nullable displayStream)
CG_AVAILABLE_BUT_DEPRECATED(
11.0, 14.0,
"There is no direct replacement for this function. Please use ScreenCaptureKit API's SCStream to replace CGDisplayStream");
#endif /* __BLOCKS__ */
CF_ASSUME_NONNULL_END
CF_IMPLICIT_BRIDGING_DISABLED
#endif /* CGDISPLAYSTREAM_H_ */

View file

@ -16,15 +16,17 @@ add_library(OBS::capture ALIAS mac-capture)
target_sources(
mac-capture
PRIVATE plugin-main.c
PRIVATE # cmake-format: sortable
audio-device-enum.c
audio-device-enum.h
CGDisplayStream.h
mac-audio.c
mac-display-capture.m
mac-screen-capture.m
mac-window-capture.m
window-utils.m
window-utils.h)
plugin-main.c
window-utils.h
window-utils.m)
target_link_libraries(mac-capture PRIVATE OBS::libobs ${COREAUDIO} ${AUDIOUNIT} ${COREFOUNDATION} ${IOSURF} ${COCOA})

View file

@ -4,7 +4,7 @@
#include <pthread.h>
#import <AvailabilityMacros.h>
#import <CoreGraphics/CGDisplayStream.h>
#import "CGDisplayStream.h"
#import <Cocoa/Cocoa.h>
#include "window-utils.h"