[CoreMediaIO] Add complete C# bindings for CoreMediaIO framework up to Xcode 26.4#25029
[CoreMediaIO] Add complete C# bindings for CoreMediaIO framework up to Xcode 26.4#25029
Conversation
Add bindings for the CoreMediaIO framework on macOS and Mac Catalyst: - 12 ObjC classes (CMIOExtensionClient, Device, Provider, Stream, etc.) - 3 protocols (CMIOExtensionStreamSource, DeviceSource, ProviderSource) - 3 enums (StreamDirection, StreamClockType, StreamDiscontinuityFlags) - ~52 NSString property fields (CMIOExtensionProperty* constants) - ~30 C P/Invoke declarations (CMIOObject*, CMIODevice*, CMIOStream*, CMIOSampleBuffer* hardware and sample buffer functions) - Async support for ConsumeSampleBuffer completion handler Resolves all 423 .todo entries (211 macOS + 212 MacCatalyst). 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.
Replace raw IntPtr parameters in CMIOInterop P/Invokes with proper C# structs: - CMIOObjectPropertyAddress (selector/scope/element) - CMIODeviceAVCCommand (AVC command buffers) - CMIODeviceRS422Command (RS422 command buffers) Add managed wrapper classes for typed API access: - CMIOObject: property query/get/set with managed types - CMIOStreamClock: clock create/post/invalidate with string names - CMIOSampleBufferExtensions: sample buffer create/query with CMSampleBuffer, CMBlockBuffer, CMFormatDescription, CVImageBuffer Add comprehensive monotouch-tests for macOS/MacCatalyst: - Struct tests (layout, round-trip, size verification) - CMIOObject property tests (system object queries) - Sample buffer create/sequence/discontinuity tests - Stream clock create/post/convert tests - Extension property/state/format/device/stream tests 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.
- Add [Mac (14, 0), MacCatalyst (17, 0)] to PixelBufferOverlaidByStaticImage field which is only available from macOS 14.0 per SDK headers, fixing introspection FieldExists failures on macOS 12/13 machines. - Add CoreMediaIO.framework to expectedFrameworks_macOS_None and expectedFrameworks_MacCatalyst_None in LinkedWithNativeLibraries test. - Update MacOSX-CoreCLR-Interpreter app size baseline to account for the new CoreMediaIO bindings (+211 KB). 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.
The test was racing between the download task completing and the URL loading system calling StopLoading on the protocol. The old code only waited for the download task to complete, then immediately asserted State == 5. But StopLoading (which sets State from 4 to 5) may be dispatched after the download task completion handler fires. Use the RunAsync overload that takes a completion check predicate to keep pumping the run loop until State reaches 5, with the existing 10s timeout as a safety net. 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.
rolfbjarne
left a comment
There was a problem hiding this comment.
I did a quick review and commented about the biggest patterns we should follow.
| [UnsupportedOSPlatform ("ios")] | ||
| [UnsupportedOSPlatform ("tvos")] | ||
| [StructLayout (LayoutKind.Sequential)] | ||
| public struct CMIODeviceAVCCommand { |
There was a problem hiding this comment.
Presumably "AVC" is an acronym, so this should be named CMIODeviceAvcCommand (which also means a [NativeName ("...")] attribute is needed).
We also try to spell out acronyms in comments (or xml docs), to make it easier for reviewers and future contributors to understand the code.
| IntPtr mCommand; | ||
| uint mCommandLength; | ||
| IntPtr mResponse; |
There was a problem hiding this comment.
There are two pointers here: pointers to what? Comments are very often useful here explaining what each field is for and how to use/expose them.
Also pointers can very often be exposed in a better way, but this requires understanding how the API in question is used to determine.
| // CMIOHardwareObject.h | ||
|
|
||
| [DllImport (Constants.CoreMediaIOLibrary)] | ||
| public static extern void CMIOObjectShow (uint objectId); |
There was a problem hiding this comment.
P/Invokes are typically private, and then exposed using a nicer C#-like API.
| [SupportedOSPlatform ("maccatalyst15.4")] | ||
| [UnsupportedOSPlatform ("ios")] | ||
| [UnsupportedOSPlatform ("tvos")] | ||
| public static unsafe class CMIOObject { |
There was a problem hiding this comment.
We try to use a narrow scope as possible for unsafe code - certainly don't put it on types, and try not to put it on members, unless almost all the code in a member requires unsafe.
|
|
||
| /// <summary>Prints a textual description of the object to stdout.</summary> | ||
| /// <param name="objectId">The object to display.</param> | ||
| public static void Show (uint objectId) |
There was a problem hiding this comment.
This looks like it could be exposed in an object-oriented way.
| @@ -0,0 +1,50 @@ | |||
| #if __MACOS__ || __MACCATALYST__ | |||
There was a problem hiding this comment.
A framework-specific conditional value is often more appropriate:
| #if __MACOS__ || __MACCATALYST__ | |
| #if HAS_COREMEDIAIO |
| // 'owne' selector = kCMIOObjectPropertyOwnedObjects | ||
| const uint OwnedObjectsSelector = 0x6F776E65; | ||
| // 'glob' scope = kCMIOObjectPropertyScopeGlobal | ||
| const uint GlobalScope = 0x676C6F62; | ||
| // Wildcard element | ||
| const uint WildcardElement = 0xFFFFFFFF; |
There was a problem hiding this comment.
Hardcoding constants in a test is often a sign of an API that can be improved: these constants should probably be available in the exposed API somwhow.
| // Just verify it doesn't crash; the result depends on attachment state | ||
| Assert.That (copyStatus, Is.LessThanOrEqualTo (0).Or.GreaterThanOrEqualTo (0), "CopySampleAttachments did not crash"); | ||
|
|
||
| source!.Dispose (); |
There was a problem hiding this comment.
Never do !.Dispose (), always use ?.Dispose ()
| int invalidateStatus = CMIOStreamClock.Invalidate (clock); | ||
| Assert.AreEqual (0, invalidateStatus, "Invalidate status"); | ||
|
|
||
| TestRuntime.CFRelease (clock); |
There was a problem hiding this comment.
This should be in a finally clause.
Although the actual fix would be to expose an object instead of a handle from the new API, and then the native handle would be freed either in a Disposing method or when the object in question was collected by the GC.
| // Use the completion-check overload to keep pumping the run loop until | ||
| // StopLoading has been called. The URL loading system may call StopLoading | ||
| // after the download task completes, so waiting only for the task is racy. | ||
| Assert.IsTrue (TestRuntime.RunAsync (TimeSpan.FromSeconds (10), task, () => CustomUrlProtocol.State >= 5), "Timed out"); |
There was a problem hiding this comment.
This looks unrelated, and should in that case go in a different pull request.
Address PR review feedback: - Rename CMIODeviceAVCCommand → CMIODeviceAvcCommand with [NativeName] - Add detailed XML docs for pointer fields explaining ownership/lifetime - Make CMIOInterop internal (P/Invokes not exposed publicly) - Convert CMIOObject to instance class with exposed constants (SystemObjectId, SelectorWildcard, GlobalScope, etc.) - Narrow unsafe scope to individual blocks, not class-level - Use Try pattern: TryCreateSampleBuffer, TryCreateNoDataMarker, etc. with [NotNullWhen(true)] and out int status - Convert CMIOStreamClock to NativeObject subclass with proper Invalidate-on-Dispose lifecycle management - Use TransientCFString instead of CFString.CreateNative - Use .AsByte() extension instead of ternary - Remove Documentation.KnownFailures additions, add XML docs instead - Use #if HAS_COREMEDIAIO in tests (framework-specific guard) - Use using blocks instead of manual CFRelease in tests - Remove unrelated UrlProtocolTest changes - Expose API constants instead of hardcoding in tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
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.
✅ [CI Build #32f2cda] Build passed (Build packages) ✅Pipeline on Agent |
✅ [PR Build #32f2cda] Build passed (Detect API changes) ✅Pipeline on Agent |
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.
✅ 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 |
✅ [CI Build #32f2cda] Build passed (Build macOS tests) ✅Pipeline on Agent |
🔥 [CI Build #32f2cda] Test results 🔥Test results❌ Tests failed on VSTS: test results 11 tests crashed, 6 tests failed, 61 tests passed. Failures❌ dotnettests tests (iOS)🔥 Failed catastrophically on VSTS: test results - dotnettests_ios (no summary found). Html Report (VSDrops) Download ❌ dotnettests tests (Multiple platforms)🔥 Failed catastrophically on VSTS: test results - dotnettests_multiple (no summary found). Html Report (VSDrops) Download ❌ fsharp tests🔥 Failed catastrophically on VSTS: test results - fsharp (no summary found). Html Report (VSDrops) Download ❌ generator tests🔥 Failed catastrophically on VSTS: test results - generator (no summary found). Html Report (VSDrops) Download ❌ introspection tests1 tests failed, 5 tests passed.Failed tests
Html Report (VSDrops) Download ❌ linker tests🔥 Failed catastrophically on VSTS: test results - linker (no summary found). Html Report (VSDrops) Download ❌ monotouch tests (iOS)🔥 Failed catastrophically on VSTS: test results - monotouch_ios (no summary found). Html Report (VSDrops) Download ❌ monotouch tests (MacCatalyst)🔥 Failed catastrophically on VSTS: test results - monotouch_maccatalyst (no summary found). Html Report (VSDrops) Download ❌ msbuild tests🔥 Failed catastrophically on VSTS: test results - msbuild (no summary found). Html Report (VSDrops) Download ❌ sharpie tests🔥 Failed catastrophically on VSTS: test results - sharpie (no summary found). Html Report (VSDrops) Download ❌ xcframework tests🔥 Failed catastrophically on VSTS: test results - xcframework (no summary found). Html Report (VSDrops) Download ❌ xtro tests🔥 Failed catastrophically on VSTS: test results - xtro (no summary found). Html Report (VSDrops) Download ❌ Tests on macOS Monterey (12) tests1 tests failed, 4 tests passed.Failed tests
Html Report (VSDrops) Download ❌ Tests on macOS Ventura (13) tests1 tests failed, 4 tests passed.Failed tests
Html Report (VSDrops) Download ❌ Tests on macOS Sonoma (14) tests1 tests failed, 4 tests passed.Failed tests
Html Report (VSDrops) Download ❌ Tests on macOS Sequoia (15) tests1 tests failed, 4 tests passed.Failed tests
Html Report (VSDrops) Download ❌ Tests on macOS Tahoe (26) tests1 tests failed, 4 tests passed.Failed tests
Html Report (VSDrops) Download Successes✅ cecil: All 1 tests passed. Html Report (VSDrops) Download macOS testsLinux Build VerificationPipeline on Agent |
Add bindings for the CoreMediaIO framework on macOS and Mac Catalyst:
Resolves all 423 .todo entries (211 macOS + 212 MacCatalyst).