[AVFoundation] Bind Xcode 27 APIs#25828
Conversation
Bind the missing Xcode 27 (beta 2) AVFoundation APIs that were tracked in tests/xtro-sharpie/api-annotations-dotnet/*-AVFoundation.todo, plus the VideoToolbox helper required by the planned-segment writing cluster. Bindings: * src/avfoundation.cs and src/AVFoundation/* - new types/members across the planned segment writing cluster, AVAudio sink/source nodes, AVAsset constituentFileURLs (macOS-only), AVCaptureMovieFileOutput / AVAssetWriter ProVideoStorage, and assorted enums/types. * src/VideoToolbox/VTCompressionSession.cs - resumable compression session support used by AVPlannedVideoSegmentWritingRequest. * src/frameworks.sources - register the new manual source file. Tooling/tests: * tests/xtro-sharpie/xtro-sharpie/EnumCheck.cs - handle the new CMPersistentTrackID-backed enum underlying type (Xcode 27). * tests/introspection/ApiTypoTest.cs - widen the "Aime" allow-list to all platforms (AVMetadataIdentifierQuickTimeMetadataAIMEData is now all-platform). * tests/introspection/iOSApiSelectorTest.cs - skip the AVAssetWriter ProVideoStorage selectors on the tvOS 27 simulator only (beta 2 simulator gap; real devices still validated). * tests/cecil-tests/Documentation.KnownFailures.txt - regenerated. * tests/xtro-sharpie/api-annotations-dotnet/*-AVFoundation.todo - removed (fully bound); tvOS .ignore updated for AVAudioSessionInterruptionReasonKey. Validation: make world clean on all 4 platforms; xtro sanity passes with all AVFoundation .todo files resolved; cecil green; introspection green on macOS, Mac Catalyst, iOS and tvOS. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Binds missing AVFoundation (Xcode 27 beta 2) APIs and updates related tooling/tests so the new surface area is covered by xtro-sharpie, introspection, and cecil documentation checks.
Changes:
- Added new AVFoundation bindings (planned segment writing cluster, audio realtime-safe nodes, ProVideoStorage-related APIs, additional enums/constants/selectors).
- Added VideoToolbox VTCompressionSession helpers to support AVPlannedVideoSegmentWritingRequest resumable compression session creation.
- Updated test infrastructure: xtro EnumCheck, introspection skips/typo allow-list, regenerated cecil documentation known failures, and removed resolved xtro
.todofiles (with a tvOS ignore exception).
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| tests/xtro-sharpie/xtro-sharpie/EnumCheck.cs | Accepts CMPersistentTrackID as a known enum underlying type to avoid xtro crashes. |
| tests/xtro-sharpie/api-annotations-dotnet/tvOS-AVFoundation.todo | Removed resolved AVFoundation todo entries (fully bound). |
| tests/xtro-sharpie/api-annotations-dotnet/tvOS-AVFoundation.ignore | Ignores AVAudioSessionInterruptionReasonKey on tvOS due to header/libclang mismatch. |
| tests/xtro-sharpie/api-annotations-dotnet/macOS-AVFoundation.todo | Removed resolved AVFoundation todo entries (fully bound). |
| tests/xtro-sharpie/api-annotations-dotnet/MacCatalyst-AVFoundation.todo | Removed resolved AVFoundation todo entries (fully bound). |
| tests/xtro-sharpie/api-annotations-dotnet/iOS-AVFoundation.todo | Removed resolved AVFoundation todo entries (fully bound). |
| tests/introspection/iOSApiSelectorTest.cs | Skips specific tvOS simulator-only missing selectors (ProVideoStorage on AVAssetWriter). |
| tests/introspection/ApiTypoTest.cs | Expands “Aime” allow-list to all platforms to reflect updated AVMetadata availability. |
| tests/cecil-tests/Documentation.KnownFailures.txt | Regenerated known-failures list for newly visible members. |
| src/VideoToolbox/VTCompressionSession.cs | Adds internal helpers to reuse trampoline/GCHandle management when AVFoundation creates native sessions. |
| src/frameworks.sources | Registers new manual AVFoundation source file for compilation. |
| src/AVFoundation/Enums.cs | Adds new enums/values introduced in Xcode 27 AVFoundation. |
| src/AVFoundation/AVTypes.cs | Adds AVPlannedVideoSegmentBoundaryGuidelines struct for segment-writing APIs. |
| src/AVFoundation/AVPlannedVideoSegmentWritingRequest.cs | New manual binding exposing resumable compression-session creation via AVFoundation selector. |
| src/AVFoundation/AVAudioSourceNode.cs | Adds realtime-safe factory APIs mapping to new AVFoundation initializers. |
| src/AVFoundation/AVAudioSinkNode.cs | Adds realtime-safe factory API mapping to new AVFoundation initializer. |
| src/avfoundation.cs | Main binding updates across AVFoundation: new types/members, new selectors, deprecations, and additional constants. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| DepthModuleTemperature = (1 << 2), | ||
| [iOS (17, 0), MacCatalyst (17, 0)] | ||
| CameraTemperature = (1uL << 3), | ||
| /// <summary>To be added.</summary> |
There was a problem hiding this comment.
We shouldn't be added new "To be added." xml docs: either write something useful, or nothing at all. There are two more instances of this further down in this file too (and since ADR is gone, something useful is much appreciated over nothing :D)
|
|
||
| [Export ("initWithVideoCodecType:encoderSpecification:mediaType:segmentConfigurations:assemblyTrackID:")] | ||
| [DesignatedInitializer] | ||
| NativeHandle Constructor ([BindAs (typeof (AVVideoCodecType))] NSString videoCodecType, [NullAllowed] NSDictionary encoderSpecification, string mediaType, AVPlannedSegmentConfiguration [] segmentConfigurations, int trackId); |
There was a problem hiding this comment.
Is there a strongly typed dictionary for encoderSpecification? Also I think AVMediaTypes (or maybe AVMediaType) can be used as the strongly typed enum for mediaType.
FWIW we should probably also expose a weakly typed overload of this constructor, where none of the parameters use a strongly typed parameter type.
|
|
||
| [Export ("resumableAssetWriterInputWithMediaType:outputSettings:sourceFormatHint:returningError:")] | ||
| [return: NullAllowed] | ||
| AVAssetWriterInput GetResumableAssetWriterInput (string mediaType, [NullAllowed] NSDictionary outputSettings, [NullAllowed] CMFormatDescription sourceFormatHint, [NullAllowed] out NSError error); |
There was a problem hiding this comment.
Same wrt mediaType, and outputSettings + weakly typed overload.
|
|
||
| // AIME = Apple Immersive Media Embedded | ||
| [NoMacCatalyst, NoTV, NoiOS, Mac (26, 0)] | ||
| [MacCatalyst (26, 0), TV (26, 0), Mac (26, 0), iOS (26, 0)] |
There was a problem hiding this comment.
Are these 26.0 availability attributes correct?
| NSString QuickTimeMetadataAimeData { get; } | ||
|
|
||
| [NoMacCatalyst, NoTV, NoiOS, Mac (26, 0)] | ||
| [MacCatalyst (26, 0), TV (26, 0), Mac (26, 0), iOS (26, 0)] |
| [SupportedOSPlatform ("macos27.0")] | ||
| [SupportedOSPlatform ("maccatalyst27.0")] | ||
| #if XAMCORE_5_0 | ||
| public static AVAudioSinkNode CreateRealtimeSafe (AVAudioSinkNodeReceiverHandler receiverHandler) |
There was a problem hiding this comment.
Manual code needs manual tests!
| #endif // XAMCORE_5_0 | ||
|
|
||
| public partial class AVAudioSinkNode { | ||
| [SupportedOSPlatform ("ios27.0")] |
There was a problem hiding this comment.
All new manual APIs should preferably have xml docs
| [StructLayout (LayoutKind.Sequential)] | ||
| public struct AVPlannedVideoSegmentBoundaryGuidelines { | ||
| /// <summary>The minimum number of frames in each incremental segment. 0 means incremental segmentation is not supported for the codec; 1 means there is no frame count restriction.</summary> | ||
| public nint MinimumFrameCount; |
There was a problem hiding this comment.
Use private fields for storage (easier to change underlying type later on if we need to), and add public property accessors.
|
/review |
|
✅ .NET for Apple Platforms PR Reviewer completed successfully! |
There was a problem hiding this comment.
Review Summary
This PR binds the missing Xcode 27 (beta 2) AVFoundation APIs with good overall quality. The bindings follow established patterns and the test updates are appropriate.
Issues Found
❌ Errors (must fix):
AVAudioSession.Activatehas incorrect platform attribute (MacCatalyst (15, 0)should beMacCatalyst (27, 0))
AVAudioSession.ActivateandDeactivateuseAction<bool, NSError>instead of named delegate types, reducing API discoverability
💡 Suggestions (consider):
- Add XML documentation to the
internalVTCompressionSession helper methods - Error handling pattern in
AVPlannedVideoSegmentWritingRequestis correct but could use a comment documenting the rationale
What's Good
✅ Platform attributes are correct throughout (except the one noted above)
✅ New types properly added to frameworks.sources
✅ EnumCheck.cs correctly updated to handle CMPersistentTrackID
✅ Test exclusions for tvOS simulator appropriately documented
✅ Nullable reference types properly used in new files
✅ Memory management in CreateResumableCompressionSession correctly handles GCHandle lifecycle
✅ Custom delegates defined for the planner callbacks
✅ ApiTypoTest updated to reflect multi-platform availability of "Aime"
Verification
- AVFoundation .todo files removed ✅
- New manual binding file added to sources ✅
- Cross-framework integration (VideoToolbox helpers) implemented correctly ✅
- Platform-specific binding (
constituentFileURLsmacOS-only) properly constrained ✅
Generated by .NET for Apple Platforms PR Reviewer for issue #25828 · 103.2 AIC · ⌖ 9.06 AIC · ⊞ 5.1K
Comment /review to run again
| [Async] | ||
| [NoTV, NoMac, NoiOS, MacCatalyst (15, 0)] | ||
| [NoMac, iOS (27, 0), TV (27, 0), MacCatalyst (15, 0)] | ||
| [Export ("activateWithOptions:completionHandler:")] |
There was a problem hiding this comment.
🤖 ❌ Platform attributes — The MacCatalyst (15, 0) attribute is incorrect here. The Activate method with options was introduced in iOS 27 / Mac Catalyst 27.
This should be:
[NoMac, iOS (27, 0), TV (27, 0), MacCatalyst (27, 0)]Rule: Every new type and member must have correct platform attributes
| [Export ("activateWithOptions:completionHandler:")] | ||
| void Activate (AVAudioSessionActivationOptions options, Action<bool, NSError> handler); | ||
|
|
||
| [Async] |
There was a problem hiding this comment.
🤖 Action<bool, NSError> delegate should be replaced with a named delegate type for better API discoverability and clarity.
When a callback has nullable parameters or return types, or when parameter meaning isn't immediately clear from the parameter list, define a named delegate type instead of using Action<>. This improves IntelliSense and makes the API self-documenting.
Consider:
delegate void AVAudioSessionActivationCompletionHandler (bool activated, [NullAllowed] NSError error);Rule: Use custom delegates over Action<> for complex callbacks
| [Async] | ||
| [NoMac, iOS (27, 0), TV (27, 0), MacCatalyst (27, 0)] | ||
| [Export ("deactivateWithOptions:completionHandler:")] | ||
| void Deactivate (AVAudioSessionDeactivationOptions options, Action<bool, NSError> handler); |
There was a problem hiding this comment.
🤖 Activate method: this Action<bool, NSError> delegate should be replaced with a named delegate type.
Consider using the same delegate type as Activate if the signatures are identical:
delegate void AVAudioSessionDeactivationCompletionHandler (bool deactivated, [NullAllowed] NSError error);Or reuse a shared delegate if the semantics are identical.
Rule: Use custom delegates over Action<> for complex callbacks
| // Helpers used by AVFoundation's AVPlannedVideoSegmentWritingRequest.CreateResumableCompressionSession, | ||
| // which creates the native VTCompressionSession through an AVFoundation selector but reuses this class's | ||
| // managed callback trampoline and GCHandle lifetime management. | ||
| internal unsafe static (IntPtr OutputCallback, IntPtr OutputCallbackRefCon) PrepareOutputCallback (VTCompressionOutputCallback? compressionOutputCallback, out GCHandle callbackHandle) |
There was a problem hiding this comment.
🤖 💡 Documentation — Add a brief XML doc comment explaining why these helper methods are internal and document the collaboration pattern with AVFoundation.
Something like:
/// <summary>Prepares callback delegates for use by AVFoundation's planned video segment writing APIs.</summary>
/// <remarks>This is an internal helper used by <see cref="AVFoundation.AVPlannedVideoSegmentWritingRequest.CreateResumableCompressionSession"/>.</remarks>
internal unsafe static (IntPtr OutputCallback, IntPtr OutputCallbackRefCon) PrepareOutputCallback (...)Rule: Comments explain "why", not "what"
|
|
||
| IntPtr handle; | ||
| try { | ||
| handle = _CreateResumableCompressionSession (IntPtr.Zero, width, height, codecType, encoderSpecification, sourceImageBufferAttributes, IntPtr.Zero, outputCallback, outputCallbackRefCon, out error); |
There was a problem hiding this comment.
🤖 💡 Error handling — The empty catch block that just rethrows is fine, but consider whether callbackHandle.Free() should be in a finally block to ensure cleanup even if the exception handling itself throws.
Current pattern is correct for the try-catch around the native call, but you could simplify slightly:
IntPtr handle;
try {
handle = _CreateResumableCompressionSession (...);
} catch {
if (callbackHandle.IsAllocated)
callbackHandle.Free ();
throw;
}This is already what you have, so this is just a confirmation that the pattern is correct. The comment is to document the rationale.
Rule: Include actionable details in exceptions
- Add strongly-typed + weakly-typed overloads for the asset writing planner APIs (AVAssetTrackPlan/AVAssetVideoTrackPlan ctors, GetSegmentBoundary- Guidelines, GetResumableAssetWriterInput) using AVMediaTypes, AVVideoCodecType and VTVideoEncoderSpecification. - Switch manual CreateResumableCompressionSession to strong VTVideoEncoderSpecification?/CVPixelBufferAttributes? to match VTCompressionSession.Create. - Replace the new "To be added." xml docs in Enums.cs with meaningful text. - Convert AVPlannedVideoSegmentBoundaryGuidelines to private fields + property accessors while preserving the sequential by-value marshaling layout. - Add xml docs to the AVAudioSinkNode/AVAudioSourceNode CreateRealtimeSafe factories and add guarded manual tests for them. - Keep the shipped MacCatalyst (15, 0) availability on AVAudioSession.Activate (raising an already-shipped intro version is a breaking change) and document why. - Regenerate cecil Documentation.KnownFailures.txt. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Fixes three CI test failures from the Xcode 27 AVFoundation bindings: * xtro (macOS): AVAudioSessionDeactivationOptions.NotifyOthersOnDeactivation triggered !extra-enum-value! because the native value is API_UNAVAILABLE(macos) while the managed value was available on macOS. The macOS AVFAudio header defines the enum *type* (no typedef-level annotation; None=0 is macOS-available) and only marks the *value* unavailable, so the fix is a value-level [NoMac] on NotifyOthersOnDeactivation, keeping the type macOS-available. Marking the whole enum [NoMac] would have excluded the type from Microsoft.macOS.dll and produced a !missing-enum! instead. * introspection (macOS + Mac Catalyst): AVAssetWriter's ProVideoStorage selectors (isProVideoStorageSupported, usesProVideoStorage, setUsesProVideoStorage:) are declared for 27.0 but not yet implemented in the 27.0 beta runtime. The binding correctly matches the header, so skip these selectors in introspection, mirroring the existing tvOS skip. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
✅ [PR Build #c1c6a63] Build passed (Detect API changes) ✅Pipeline on Agent |
This comment has been minimized.
This comment has been minimized.
✅ API diff for current PR / commitNET (empty diffs)✅ API diff vs stableNET (empty diffs)ℹ️ Generator diffGenerator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes) Pipeline on Agent |
✅ [PR Build #c1c6a63] Build passed (Build packages) ✅Pipeline on Agent |
✅ [PR Build #c1c6a63] Build passed (Build macOS tests) ✅Pipeline on Agent |
🚀 [CI Build #c1c6a63] Test results 🚀Test results✅ All tests passed on VSTS: test results. 🎉 All 196 tests passed 🎉 Tests counts✅ assembly-processing: All 1 tests passed. Html Report (VSDrops) Download macOS tests✅ Tests on macOS Sonoma (14): All 5 tests passed. [attempt 2] Html Report (VSDrops) Download Linux Build VerificationPipeline on Agent |
Bind the missing Xcode 27 (beta 2) AVFoundation APIs that were tracked in tests/xtro-sharpie/api-annotations-dotnet/*-AVFoundation.todo, plus the VideoToolbox helper required by the planned-segment writing cluster.
Bindings:
Tooling/tests:
Validation: make world clean on all 4 platforms; xtro sanity passes with all AVFoundation .todo files resolved; cecil green; introspection green on macOS, Mac Catalyst, iOS and tvOS.