Skip to content

[CoreMediaIO] Add complete C# bindings for CoreMediaIO framework up to Xcode 26.4#25029

Draft
dalexsoto wants to merge 7 commits intomainfrom
dev/alex/CoreMediaIO
Draft

[CoreMediaIO] Add complete C# bindings for CoreMediaIO framework up to Xcode 26.4#25029
dalexsoto wants to merge 7 commits intomainfrom
dev/alex/CoreMediaIO

Conversation

@dalexsoto
Copy link
Copy Markdown
Member

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).

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>
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

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>
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

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>
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

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>
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

Copy link
Copy Markdown
Member

@rolfbjarne rolfbjarne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a quick review and commented about the biggest patterns we should follow.

Comment thread src/CoreMediaIO/CMIODeviceAVCCommand.cs Outdated
[UnsupportedOSPlatform ("ios")]
[UnsupportedOSPlatform ("tvos")]
[StructLayout (LayoutKind.Sequential)]
public struct CMIODeviceAVCCommand {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/CoreMediaIO/CMIODeviceAVCCommand.cs Outdated
Comment on lines +16 to +18
IntPtr mCommand;
uint mCommandLength;
IntPtr mResponse;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/CoreMediaIO/CMIOInterop.cs Outdated
// CMIOHardwareObject.h

[DllImport (Constants.CoreMediaIOLibrary)]
public static extern void CMIOObjectShow (uint objectId);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P/Invokes are typically private, and then exposed using a nicer C#-like API.

Comment thread src/CoreMediaIO/CMIOObject.cs Outdated
[SupportedOSPlatform ("maccatalyst15.4")]
[UnsupportedOSPlatform ("ios")]
[UnsupportedOSPlatform ("tvos")]
public static unsafe class CMIOObject {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/CoreMediaIO/CMIOObject.cs Outdated

/// <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)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it could be exposed in an object-oriented way.

@@ -0,0 +1,50 @@
#if __MACOS__ || __MACCATALYST__
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A framework-specific conditional value is often more appropriate:

Suggested change
#if __MACOS__ || __MACCATALYST__
#if HAS_COREMEDIAIO

Comment on lines +16 to +21
// 'owne' selector = kCMIOObjectPropertyOwnedObjects
const uint OwnedObjectsSelector = 0x6F776E65;
// 'glob' scope = kCMIOObjectPropertyScopeGlobal
const uint GlobalScope = 0x676C6F62;
// Wildcard element
const uint WildcardElement = 0xFFFFFFFF;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 ();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never do !.Dispose (), always use ?.Dispose ()

int invalidateStatus = CMIOStreamClock.Invalidate (clock);
Assert.AreEqual (0, invalidateStatus, "Invalidate status");

TestRuntime.CFRelease (clock);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Copy Markdown

Azure Pipelines:
Successfully started running 1 pipeline(s).

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines:
Successfully started running 1 pipeline(s).

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2
Copy link
Copy Markdown
Collaborator

✅ [CI Build #32f2cda] Build passed (Build packages) ✅

Pipeline on Agent
Hash: 32f2cdac63bffe109754b4135b59cded567b4d1f [PR build]

@vs-mobiletools-engineering-service2
Copy link
Copy Markdown
Collaborator

✅ [PR Build #32f2cda] Build passed (Detect API changes) ✅

Pipeline on Agent
Hash: 32f2cdac63bffe109754b4135b59cded567b4d1f [PR build]

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2
Copy link
Copy Markdown
Collaborator

✅ API diff for current PR / commit

NET (empty diffs)

✅ API diff vs stable

NET (empty diffs)

ℹ️ Generator diff

Generator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes)

Pipeline on Agent
Hash: 32f2cdac63bffe109754b4135b59cded567b4d1f [PR build]

@vs-mobiletools-engineering-service2
Copy link
Copy Markdown
Collaborator

✅ [CI Build #32f2cda] Build passed (Build macOS tests) ✅

Pipeline on Agent
Hash: 32f2cdac63bffe109754b4135b59cded567b4d1f [PR build]

@vs-mobiletools-engineering-service2
Copy link
Copy Markdown
Collaborator

🔥 [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 tests

1 tests failed, 5 tests passed.

Failed tests

  • introspection/Mac Catalyst/Debug: Failed (Test run failed.
    Tests run: 40 Passed: 38 Inconclusive: 0 Failed: 1 Ignored: 1)

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) tests

1 tests failed, 4 tests passed.

Failed tests

  • introspection: Failed (exit code 2)
    • CheckFailAttachments : System.InvalidOperationException : Could not create the new instance for type CMIOStreamClock.
    • CheckFailAttachments : System.InvalidOperationException : Could not create the new instance for type CMIOStreamClock.

Html Report (VSDrops) Download

❌ Tests on macOS Ventura (13) tests

1 tests failed, 4 tests passed.

Failed tests

  • introspection: Failed (exit code 2)
    • CheckFailAttachments : System.InvalidOperationException : Could not create the new instance for type CMIOStreamClock.
    • CheckFailAttachments : System.InvalidOperationException : Could not create the new instance for type CMIOStreamClock.

Html Report (VSDrops) Download

❌ Tests on macOS Sonoma (14) tests

1 tests failed, 4 tests passed.

Failed tests

  • introspection: Failed (exit code 2)
    • CheckFailAttachments : System.InvalidOperationException : Could not create the new instance for type CMIOStreamClock.

Html Report (VSDrops) Download

❌ Tests on macOS Sequoia (15) tests

1 tests failed, 4 tests passed.

Failed tests

  • introspection: Failed (exit code 2)
    • CheckFailAttachments : System.InvalidOperationException : Could not create the new instance for type CMIOStreamClock.
    • CheckFailAttachments : System.InvalidOperationException : Could not create the new instance for type CMIOStreamClock.

Html Report (VSDrops) Download

❌ Tests on macOS Tahoe (26) tests

1 tests failed, 4 tests passed.

Failed tests

  • introspection: Failed (exit code 2)
    • CheckFailAttachments : System.InvalidOperationException : Could not create the new instance for type CMIOStreamClock.
    • CheckFailAttachments : System.InvalidOperationException : Could not create the new instance for type CMIOStreamClock.

Html Report (VSDrops) Download

Successes

✅ cecil: All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (MacCatalyst): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (macOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (tvOS): All 1 tests passed. Html Report (VSDrops) Download
✅ framework: All 2 tests passed. Html Report (VSDrops) Download
✅ interdependent-binding-projects: All 4 tests passed. Html Report (VSDrops) Download
✅ monotouch (macOS): All 12 tests passed. Html Report (VSDrops) Download
✅ monotouch (tvOS): All 11 tests passed. Html Report (VSDrops) Download
✅ windows: All 3 tests passed. Html Report (VSDrops) Download

macOS tests

Linux Build Verification

Linux build succeeded

Pipeline on Agent
Hash: 32f2cdac63bffe109754b4135b59cded567b4d1f [PR build]

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants