From 9179ea109c436db1f6d78ddf27962246af0de808 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Thu, 4 Jun 2026 15:57:37 +0200 Subject: [PATCH 1/3] [AVFoundation] Fix signature for more LoadTrack*/LoadTracks* methods. Fixes #25606. Fix the completion handler parameter types for LoadTrack/LoadTracksWithMediaType/ LoadTracksWithMediaCharacteristic methods in: - AVAsset (AVCompositionTrack -> AVAssetTrack) - AVMutableMovie (AVMovieTrack -> AVMutableMovieTrack) - AVFragmentedMovie (AVMutableCompositionTrack -> AVFragmentedMovieTrack) - AVComposition (AVMutableCompositionTrack -> AVCompositionTrack) Fixes https://github.com/dotnet/macios/issues/25606. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/avfoundation.cs | 224 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) diff --git a/src/avfoundation.cs b/src/avfoundation.cs index 072eac814b82..c97568acb363 100644 --- a/src/avfoundation.cs +++ b/src/avfoundation.cs @@ -5674,22 +5674,67 @@ interface AVAsset : NSCopying { [Export ("loadMetadataForFormat:completionHandler:")] void LoadMetadata (string format, Action, NSError> completionHandler); +#if !XAMCORE_5_0 + [Obsolete ("Call 'LoadTrack2' instead.")] [Async] [TV (15, 0), iOS (15, 0), MacCatalyst (15, 0)] [Export ("loadTrackWithTrackID:completionHandler:")] void LoadTrack (int trackId, Action completionHandler); +#endif + + [Async] + [TV (15, 0), iOS (15, 0), MacCatalyst (15, 0)] + [Export ("loadTrackWithTrackID:completionHandler:")] +#if XAMCORE_5_0 + void LoadTrack (int trackId, AVAssetLoadTrackCallback completionHandler); +#else + [Sealed] + void LoadTrack2 (int trackId, AVAssetLoadTrackCallback completionHandler); +#endif +#if !XAMCORE_5_0 + [Obsolete ("Call the 'LoadTrackWithMediaCharacteristics (..., AVAssetLoadTracksCallback)' overload instead (or the 'LoadTrackWithMediaCharacteristics2Async' method).")] [Async] [TV (15, 0), iOS (15, 0), MacCatalyst (15, 0)] [Export ("loadTracksWithMediaCharacteristic:completionHandler:")] void LoadTrackWithMediaCharacteristics (string mediaCharacteristic, Action, NSError> completionHandler); +#endif + +#if XAMCORE_5_0 + [Async] +#else + [Async ("LoadTrackWithMediaCharacteristics2Async")] + [Sealed] +#endif + [TV (15, 0), iOS (15, 0), MacCatalyst (15, 0)] + [Export ("loadTracksWithMediaCharacteristic:completionHandler:")] + void LoadTrackWithMediaCharacteristics (string mediaCharacteristic, AVAssetLoadTracksCallback completionHandler); +#if !XAMCORE_5_0 + [Obsolete ("Call 'LoadTracksWithMediaType (..., AVAssetLoadTracksCallback)' instead (or the 'LoadTracksWithMediaType' method).")] [Async] [TV (15, 0), iOS (15, 0), MacCatalyst (15, 0)] [Export ("loadTracksWithMediaType:completionHandler:")] void LoadTracksWithMediaType (string mediaType, Action, NSError> completionHandler); +#endif + +#if XAMCORE_5_0 + [Async] +#else + [Async ("LoadTracksWithMediaType2Async")] + [Sealed] +#endif + [TV (15, 0), iOS (15, 0), MacCatalyst (15, 0)] + [Export ("loadTracksWithMediaType:completionHandler:")] + void LoadTracksWithMediaType (string mediaType, AVAssetLoadTracksCallback completionHandler); + + [Wrap ("LoadTracksWithMediaType (mediaType.GetConstant ()!, completionHandler)")] + void LoadTracksWithMediaType (AVMediaTypes mediaType, AVAssetLoadTracksCallback completionHandler); } + delegate void AVAssetLoadTrackCallback ([NullAllowed] AVAssetTrack track, [NullAllowed] NSError error); + delegate void AVAssetLoadTracksCallback ([NullAllowed] AVAssetTrack[] tracks, [NullAllowed] NSError error); + interface IAVFragmentMinding { } /// Interface for to support tracking whether fragments have been appended to a fragmented asset. @@ -12657,22 +12702,66 @@ interface AVMovie_AVMovieTrackInspection { [Wrap ("This.GetTracksWithMediaCharacteristic (mediaCharacteristic.GetConstant ()!)")] AVMovieTrack [] GetTracks (AVMediaCharacteristics mediaCharacteristic); +#if !XAMCORE_5_0 + [Obsolete ("Call the 'LoadTrack (..., AVMovieLoadTracksCallback)' overload instead (or the 'LoadTrack2Async' method).")] [Async] [NoTV, iOS (15, 0), MacCatalyst (15, 0)] [Export ("loadTrackWithTrackID:completionHandler:")] void LoadTrack (int trackId, Action completionHandler); +#endif + +#if XAMCORE_5_0 + [Async] +#else + [Async ("LoadTrack2Async")] +#endif + [NoTV, iOS (15, 0), MacCatalyst (15, 0)] + [Export ("loadTrackWithTrackID:completionHandler:")] + void LoadTrack (int trackId, AVMovieLoadTrackCallback completionHandler); +#if !XAMCORE_5_0 + [Obsolete ("Call the 'LoadTracksWithMediaType (..., AVMovieLoadTracksCallback)' overload instead (or the 'LoadTracksWithMediaType2Async' method).")] [Async] [NoTV, iOS (15, 0), MacCatalyst (15, 0)] [Export ("loadTracksWithMediaType:completionHandler:")] void LoadTracksWithMediaType (string mediaType, Action, NSError> completionHandler); +#endif + +#if XAMCORE_5_0 + [Async] +#else + [Async ("LoadTracksWithMediaType2Async")] +#endif + [NoTV, iOS (15, 0), MacCatalyst (15, 0)] + [Export ("loadTracksWithMediaType:completionHandler:")] + void LoadTracksWithMediaType (string mediaType, AVMovieLoadTracksCallback completionHandler); + [Async] + [NoTV, iOS (15, 0), MacCatalyst (15, 0)] + [Wrap ("This.LoadTracksWithMediaType (mediaType.GetConstant ()!, completionHandler)")] + void LoadTracksWithMediaType (AVMediaTypes mediaType, AVMovieLoadTracksCallback completionHandler); + +#if !XAMCORE_5_0 + [Obsolete ("Call the 'LoadTracksWithMediaCharacteristic (..., AVMovieLoadTracksCallback)' overload instead (or the 'LoadTracksWithMediaCharacteristic2Async' method).")] [Async] [NoTV, iOS (15, 0), MacCatalyst (15, 0)] [Export ("loadTracksWithMediaCharacteristic:completionHandler:")] void LoadTracksWithMediaCharacteristic (string mediaCharacteristic, Action, NSError> completionHandler); +#endif + +#if XAMCORE_5_0 + [Async] +#else + [Async ("LoadTracksWithMediaCharacteristic2Async")] +#endif + [NoTV, iOS (15, 0), MacCatalyst (15, 0)] + [Export ("loadTracksWithMediaCharacteristic:completionHandler:")] + void LoadTracksWithMediaCharacteristic (string mediaCharacteristic, AVMovieLoadTracksCallback completionHandler); } + delegate void AVMovieLoadTrackCallback ([NullAllowed] AVMovieTrack track, [NullAllowed] NSError error); + delegate void AVMovieLoadTracksCallback ([NullAllowed] AVMovieTrack[] tracks, [NullAllowed] NSError error); + [NoTV, iOS (13, 0)] [MacCatalyst (13, 1)] [BaseType (typeof (AVMovie))] @@ -12736,20 +12825,64 @@ interface AVMutableMovie { [Export ("interleavingPeriod", ArgumentSemantic.Assign)] CMTime InterleavingPeriod { get; set; } +#if !XAMCORE_5_0 + [Obsolete ("Call 'LoadTrack2' instead.")] [Async] [NoTV, iOS (15, 0), MacCatalyst (15, 0)] [Export ("loadTrackWithTrackID:completionHandler:")] void LoadTrack (int trackId, Action completionHandler); +#endif + + [Async] + [NoTV, iOS (15, 0), MacCatalyst (15, 0)] + [Export ("loadTrackWithTrackID:completionHandler:")] +#if XAMCORE_5_0 + void LoadTrack (int trackId, AVMutableMovieLoadTrackCallback completionHandler); +#else + [Sealed] + void LoadTrack2 (int trackId, AVMutableMovieLoadTrackCallback completionHandler); +#endif +#if !XAMCORE_5_0 + [Obsolete ("Call the 'LoadTracksWithMediaType (..., AVMutableMovieLoadTracksCallback)' overload instead (or the 'LoadTracksWithMediaCharacteristic2Async' method).")] [Async] [NoTV, iOS (15, 0), MacCatalyst (15, 0)] [Export ("loadTracksWithMediaType:completionHandler:")] void LoadTracksWithMediaType (string mediaType, Action, NSError> completionHandler); +#endif +#if XAMCORE_5_0 + [Async] +#else + [Async ("LoadTracksWithMediaType2Async")] + [Sealed] +#endif + [NoTV, iOS (15, 0), MacCatalyst (15, 0)] + [Export ("loadTracksWithMediaType:completionHandler:")] + void LoadTracksWithMediaType (string mediaType, AVMutableMovieLoadTracksCallback completionHandler); + + [Async] + [NoTV, iOS (15, 0), MacCatalyst (15, 0)] + [Wrap ("LoadTracksWithMediaType (mediaType.GetConstant ()!, completionHandler)")] + void LoadTracksWithMediaType (AVMediaTypes mediaType, AVMutableMovieLoadTracksCallback completionHandler); + +#if !XAMCORE_5_0 + [Obsolete ("Call the 'LoadTracksWithMediaCharacteristic (..., AVMutableMovieLoadTracksCallback)' overload instead (or the 'LoadTracksWithMediaCharacteristic2Async' method).")] [Async] [NoTV, iOS (15, 0), MacCatalyst (15, 0)] [Export ("loadTracksWithMediaCharacteristic:completionHandler:")] void LoadTracksWithMediaCharacteristic (string mediaCharacteristic, Action, NSError> completionHandler); +#endif + +#if XAMCORE_5_0 + [Async] +#else + [Async ("LoadTracksWithMediaCharacteristic2Async")] + [Sealed] +#endif + [NoTV, iOS (15, 0), MacCatalyst (15, 0)] + [Export ("loadTracksWithMediaCharacteristic:completionHandler:")] + void LoadTracksWithMediaCharacteristic (string mediaCharacteristic, AVMutableMovieLoadTracksCallback completionHandler); // inlined from the AVMutableMovie (SynchronousAssetInterface) category [Export ("metadataForFormat:")] @@ -12773,6 +12906,9 @@ interface AVMutableMovie { int GetUnusedTrackId (); } + delegate void AVMutableMovieLoadTrackCallback ([NullAllowed] AVMutableMovieTrack track, [NullAllowed] NSError error); + delegate void AVMutableMovieLoadTracksCallback ([NullAllowed] AVMutableMovieTrack[] tracks, [NullAllowed] NSError error); + [NoTV, iOS (13, 0)] [MacCatalyst (13, 1)] [Category] @@ -12973,22 +13109,66 @@ interface AVFragmentedMovie_AVFragmentedMovieTrackInspection { [Wrap ("This.GetTracksWithMediaCharacteristic (mediaCharacteristic.GetConstant ()!)")] AVFragmentedMovieTrack [] GetTracks (AVMediaCharacteristics mediaCharacteristic); +#if !XAMCORE_5_0 + [Obsolete ("Call the 'LoadTrack (..., AVFragmentedMovieLoadTrackCallback)' overload instead (or the 'LoadTrack2Async' method).")] [Async] [iOS (15, 0), MacCatalyst (15, 0)] [Export ("loadTrackWithTrackID:completionHandler:")] void LoadTrack (int trackId, Action completionHandler); +#endif + +#if XAMCORE_5_0 + [Async] +#else + [Async ("LoadTrack2Async")] +#endif + [iOS (15, 0), MacCatalyst (15, 0)] + [Export ("loadTrackWithTrackID:completionHandler:")] + void LoadTrack (int trackId, AVFragmentedMovieLoadTrackCallback completionHandler); +#if !XAMCORE_5_0 + [Obsolete ("Call the 'LoadTracksWithMediaType (..., AVFragmentedMovieLoadTracksCallback)' overload instead (or the 'LoadTracksWithMediaType2Async' method).")] [Async] [iOS (15, 0), MacCatalyst (15, 0)] [Export ("loadTracksWithMediaType:completionHandler:")] void LoadTracksWithMediaType (string mediaType, Action, NSError> completionHandler); +#endif + +#if XAMCORE_5_0 + [Async] +#else + [Async ("LoadTracksWithMediaType2Async")] +#endif + [iOS (15, 0), MacCatalyst (15, 0)] + [Export ("loadTracksWithMediaType:completionHandler:")] + void LoadTracksWithMediaType (string mediaType, AVFragmentedMovieLoadTracksCallback completionHandler); + [Async] + [iOS (15, 0), MacCatalyst (15, 0)] + [Wrap ("This.LoadTracksWithMediaType (mediaType.GetConstant ()!, completionHandler)")] + void LoadTracksWithMediaType (AVMediaTypes mediaType, AVFragmentedMovieLoadTracksCallback completionHandler); + +#if !XAMCORE_5_0 + [Obsolete ("Call the 'LoadTracksWithMediaCharacteristic (..., AVFragmentedMovieLoadTracksCallback)' overload instead (or the 'LoadTracksWithMediaCharacteristic2Async' method).")] [Async] [iOS (15, 0), MacCatalyst (15, 0)] [Export ("loadTracksWithMediaCharacteristic:completionHandler:")] void LoadTracksWithMediaCharacteristic (string mediaCharacteristic, Action, NSError> completionHandler); +#endif + +#if XAMCORE_5_0 + [Async] +#else + [Async ("LoadTracksWithMediaCharacteristic2Async")] +#endif + [iOS (15, 0), MacCatalyst (15, 0)] + [Export ("loadTracksWithMediaCharacteristic:completionHandler:")] + void LoadTracksWithMediaCharacteristic (string mediaCharacteristic, AVFragmentedMovieLoadTracksCallback completionHandler); } + delegate void AVFragmentedMovieLoadTrackCallback ([NullAllowed] AVFragmentedMovieTrack track, [NullAllowed] NSError error); + delegate void AVFragmentedMovieLoadTracksCallback ([NullAllowed] AVFragmentedMovieTrack[] tracks, [NullAllowed] NSError error); + [iOS (13, 0), NoTV] [MacCatalyst (13, 1)] [BaseType (typeof (AVFragmentedAssetMinder))] @@ -13563,22 +13743,66 @@ interface AVComposition_AVCompositionTrackInspection { [Wrap ("This.GetTracksWithMediaCharacteristic (mediaCharacteristic.GetConstant ()!)")] AVCompositionTrack [] GetTracks (AVMediaCharacteristics mediaCharacteristic); +#if !XAMCORE_5_0 + [Obsolete ("Call the 'LoadTrack (..., AVCompositionLoadTrackCallback)' overload instead (or the 'LoadTrack2Async' method).")] [Async] [TV (15, 0), iOS (15, 0), MacCatalyst (15, 0)] [Export ("loadTrackWithTrackID:completionHandler:")] void LoadTrack (int trackId, Action completionHandler); +#endif +#if XAMCORE_5_0 + [Async] +#else + [Async ("LoadTrack2Async")] +#endif + [TV (15, 0), iOS (15, 0), MacCatalyst (15, 0)] + [Export ("loadTrackWithTrackID:completionHandler:")] + void LoadTrack (int trackId, AVCompositionLoadTrackCallback completionHandler); + +#if !XAMCORE_5_0 + [Obsolete ("Call the 'LoadTracksWithMediaType (..., AVCompositionLoadTracksCallback)' overload instead (or the 'LoadTracksWithMediaType' method).")] [Async] [TV (15, 0), iOS (15, 0), MacCatalyst (15, 0)] [Export ("loadTracksWithMediaType:completionHandler:")] void LoadTracksWithMediaType (string mediaType, Action, NSError> completionHandler); +#endif +#if XAMCORE_5_0 + [Async] +#else + [Async ("LoadTracksWithMediaType2Async")] +#endif + [TV (15, 0), iOS (15, 0), MacCatalyst (15, 0)] + [Export ("loadTracksWithMediaType:completionHandler:")] + void LoadTracksWithMediaType (string mediaType, AVCompositionLoadTracksCallback completionHandler); + + [Async] + [TV (15, 0), iOS (15, 0), MacCatalyst (15, 0)] + [Wrap ("This.LoadTracksWithMediaType (mediaType.GetConstant ()!, completionHandler)")] + void LoadTracksWithMediaType (AVMediaTypes mediaType, AVCompositionLoadTracksCallback completionHandler); + +#if !XAMCORE_5_0 + [Obsolete ("Call the 'LoadTracksWithMediaCharacteristic (..., AVCompositionLoadTracksCallback)' overload instead (or the 'LoadTracksWithMediaCharacteristic' method).")] [Async] [TV (15, 0), iOS (15, 0), MacCatalyst (15, 0)] [Export ("loadTracksWithMediaCharacteristic:completionHandler:")] void LoadTracksWithMediaCharacteristic (string mediaCharacteristic, Action, NSError> completionHandler); +#endif + +#if XAMCORE_5_0 + [Async] +#else + [Async ("LoadTracksWithMediaCharacteristic2Async")] +#endif + [TV (15, 0), iOS (15, 0), MacCatalyst (15, 0)] + [Export ("loadTracksWithMediaCharacteristic:completionHandler:")] + void LoadTracksWithMediaCharacteristic (string mediaCharacteristic, AVCompositionLoadTracksCallback completionHandler); } + delegate void AVCompositionLoadTrackCallback ([NullAllowed] AVCompositionTrack track, [NullAllowed] NSError error); + delegate void AVCompositionLoadTracksCallback ([NullAllowed] AVCompositionTrack[] tracks, [NullAllowed] NSError error); + [MacCatalyst (13, 1)] [BaseType (typeof (AVComposition))] interface AVMutableComposition { From ec5a5b3788e84bd7f080b6126b4d2b89f640de88 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Thu, 4 Jun 2026 19:11:04 +0200 Subject: [PATCH 2/3] [tests] Add unit tests for LoadTrack/LoadTracks methods with corrected signatures. Tests cover the new correctly-typed callback overloads for: - AVAsset.LoadTrack2, LoadTrackWithMediaCharacteristics, LoadTracksWithMediaType - AVMovie.LoadTrack, LoadTracksWithMediaType, LoadTracksWithMediaCharacteristic - AVMutableMovie.LoadTrack2, LoadTracksWithMediaType, LoadTracksWithMediaCharacteristic - AVComposition.LoadTrack, LoadTracksWithMediaType, LoadTracksWithMediaCharacteristic Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../AVFoundation/AVAssetLoadTracksTest.cs | 414 ++++++++++++++++++ 1 file changed, 414 insertions(+) create mode 100644 tests/monotouch-test/AVFoundation/AVAssetLoadTracksTest.cs diff --git a/tests/monotouch-test/AVFoundation/AVAssetLoadTracksTest.cs b/tests/monotouch-test/AVFoundation/AVAssetLoadTracksTest.cs new file mode 100644 index 000000000000..97102d25f0a2 --- /dev/null +++ b/tests/monotouch-test/AVFoundation/AVAssetLoadTracksTest.cs @@ -0,0 +1,414 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.IO; +using System.Threading.Tasks; + +using AVFoundation; +using CoreMedia; + +#nullable enable + +namespace MonoTouchFixtures.AVFoundation { + + [TestFixture] + [Preserve (AllMembers = true)] + public class AVAssetLoadTracksTest { + + static string VideoPath => Path.Combine (NSBundle.MainBundle.ResourcePath, "xamvideotest.mp4"); + + #region AVAsset + + [Test] + public void AVAsset_LoadTrack2 () + { + TestRuntime.AssertXcodeVersion (13, 0); + + using var url = NSUrl.FromFilename (VideoPath); + using var asset = AVAsset.FromUrl (url); + + var tcs = new TaskCompletionSource (); + asset.LoadTrack2 (1, (track, error) => { + tcs.TrySetResult (track); + }); + + Assert.That (tcs.Task.Wait (TimeSpan.FromSeconds (10)), Is.True, "Timed out"); + var result = tcs.Task.Result; + if (result is not null) + Assert.That (result, Is.InstanceOf (), "result type"); + } + + [Test] + public void AVAsset_LoadTrackWithMediaCharacteristics () + { + TestRuntime.AssertXcodeVersion (13, 0); + + using var url = NSUrl.FromFilename (VideoPath); + using var asset = AVAsset.FromUrl (url); + + var tcs = new TaskCompletionSource (); + asset.LoadTrackWithMediaCharacteristics (AVMediaCharacteristics.Visual.GetConstant ()!, (tracks, error) => { + tcs.TrySetResult (tracks); + }); + + Assert.That (tcs.Task.Wait (TimeSpan.FromSeconds (10)), Is.True, "Timed out"); + var result = tcs.Task.Result; + Assert.That (result, Is.Not.Null, "result"); + Assert.That (result!.Length, Is.GreaterThan (0), "result.Length"); + Assert.That (result [0], Is.InstanceOf (), "result[0] type"); + } + + [Test] + public void AVAsset_LoadTracksWithMediaType () + { + TestRuntime.AssertXcodeVersion (13, 0); + + using var url = NSUrl.FromFilename (VideoPath); + using var asset = AVAsset.FromUrl (url); + + var tcs = new TaskCompletionSource (); + asset.LoadTracksWithMediaType (AVMediaTypes.Video.GetConstant ()!, (AVAssetLoadTracksCallback) ((tracks, error) => { + tcs.TrySetResult (tracks); + })); + + Assert.That (tcs.Task.Wait (TimeSpan.FromSeconds (10)), Is.True, "Timed out"); + var result = tcs.Task.Result; + Assert.That (result, Is.Not.Null, "result"); + Assert.That (result!.Length, Is.GreaterThan (0), "result.Length"); + Assert.That (result [0], Is.InstanceOf (), "result[0] type"); + } + + [Test] + public void AVAsset_LoadTracksWithMediaType_Enum () + { + TestRuntime.AssertXcodeVersion (13, 0); + + using var url = NSUrl.FromFilename (VideoPath); + using var asset = AVAsset.FromUrl (url); + + var tcs = new TaskCompletionSource (); + asset.LoadTracksWithMediaType (AVMediaTypes.Video, (AVAssetLoadTracksCallback) ((tracks, error) => { + tcs.TrySetResult (tracks); + })); + + Assert.That (tcs.Task.Wait (TimeSpan.FromSeconds (10)), Is.True, "Timed out"); + var result = tcs.Task.Result; + Assert.That (result, Is.Not.Null, "result"); + Assert.That (result!.Length, Is.GreaterThan (0), "result.Length"); + Assert.That (result [0], Is.InstanceOf (), "result[0] type"); + } + + #endregion + + #region AVMovie +#if !__TVOS__ + + [Test] + public void AVMovie_LoadTrack () + { + TestRuntime.AssertXcodeVersion (13, 0); + + using var url = NSUrl.FromFilename (VideoPath); + using var movie = new AVMovie (url, (NSDictionary?) null); + + var tcs = new TaskCompletionSource (); + movie.LoadTrack (1, (AVMovieLoadTrackCallback) ((track, error) => { + tcs.TrySetResult (track); + })); + + Assert.That (tcs.Task.Wait (TimeSpan.FromSeconds (10)), Is.True, "Timed out"); + var result = tcs.Task.Result; + if (result is not null) + Assert.That (result, Is.InstanceOf (), "result type"); + } + + [Test] + public void AVMovie_LoadTracksWithMediaType () + { + TestRuntime.AssertXcodeVersion (13, 0); + + using var url = NSUrl.FromFilename (VideoPath); + using var movie = new AVMovie (url, (NSDictionary?) null); + + var tcs = new TaskCompletionSource (); + movie.LoadTracksWithMediaType (AVMediaTypes.Video.GetConstant ()!, (AVMovieLoadTracksCallback) ((tracks, error) => { + tcs.TrySetResult (tracks); + })); + + Assert.That (tcs.Task.Wait (TimeSpan.FromSeconds (10)), Is.True, "Timed out"); + var result = tcs.Task.Result; + // mp4 files may not be recognized as movies, so tracks could be null + if (result is not null) { + Assert.That (result.Length, Is.GreaterThan (0), "result.Length"); + Assert.That (result [0], Is.InstanceOf (), "result[0] type"); + } + } + + [Test] + public void AVMovie_LoadTracksWithMediaType_Enum () + { + TestRuntime.AssertXcodeVersion (13, 0); + + using var url = NSUrl.FromFilename (VideoPath); + using var movie = new AVMovie (url, (NSDictionary?) null); + + var tcs = new TaskCompletionSource (); + movie.LoadTracksWithMediaType (AVMediaTypes.Video, (AVMovieLoadTracksCallback) ((tracks, error) => { + tcs.TrySetResult (tracks); + })); + + Assert.That (tcs.Task.Wait (TimeSpan.FromSeconds (10)), Is.True, "Timed out"); + var result = tcs.Task.Result; + if (result is not null) { + Assert.That (result.Length, Is.GreaterThan (0), "result.Length"); + Assert.That (result [0], Is.InstanceOf (), "result[0] type"); + } + } + + [Test] + public void AVMovie_LoadTracksWithMediaCharacteristic () + { + TestRuntime.AssertXcodeVersion (13, 0); + + using var url = NSUrl.FromFilename (VideoPath); + using var movie = new AVMovie (url, (NSDictionary?) null); + + var tcs = new TaskCompletionSource (); + movie.LoadTracksWithMediaCharacteristic (AVMediaCharacteristics.Visual.GetConstant ()!, (AVMovieLoadTracksCallback) ((tracks, error) => { + tcs.TrySetResult (tracks); + })); + + Assert.That (tcs.Task.Wait (TimeSpan.FromSeconds (10)), Is.True, "Timed out"); + var result = tcs.Task.Result; + if (result is not null) { + Assert.That (result.Length, Is.GreaterThan (0), "result.Length"); + Assert.That (result [0], Is.InstanceOf (), "result[0] type"); + } + } + + #endregion + + #region AVMutableMovie + + [Test] + public void AVMutableMovie_LoadTrack2 () + { + TestRuntime.AssertXcodeVersion (13, 0); + + using var url = NSUrl.FromFilename (VideoPath); + using var movie = new AVMutableMovie (url, (NSDictionary?) null, out var initError); + if (initError is not null) + Assert.Ignore ($"Could not create AVMutableMovie from test file: {initError.LocalizedDescription}"); + + var tcs = new TaskCompletionSource (); + movie.LoadTrack2 (1, (track, error) => { + tcs.TrySetResult (track); + }); + + Assert.That (tcs.Task.Wait (TimeSpan.FromSeconds (10)), Is.True, "Timed out"); + var result = tcs.Task.Result; + if (result is not null) + Assert.That (result, Is.InstanceOf (), "result type"); + } + + [Test] + public void AVMutableMovie_LoadTracksWithMediaType () + { + TestRuntime.AssertXcodeVersion (13, 0); + + using var url = NSUrl.FromFilename (VideoPath); + using var movie = new AVMutableMovie (url, (NSDictionary?) null, out var initError); + if (initError is not null) + Assert.Ignore ($"Could not create AVMutableMovie from test file: {initError.LocalizedDescription}"); + + var tcs = new TaskCompletionSource (); + movie.LoadTracksWithMediaType (AVMediaTypes.Video.GetConstant ()!, (AVMutableMovieLoadTracksCallback) ((tracks, error) => { + tcs.TrySetResult (tracks); + })); + + Assert.That (tcs.Task.Wait (TimeSpan.FromSeconds (10)), Is.True, "Timed out"); + var result = tcs.Task.Result; + if (result is not null) { + Assert.That (result.Length, Is.GreaterThan (0), "result.Length"); + Assert.That (result [0], Is.InstanceOf (), "result[0] type"); + } + } + + [Test] + public void AVMutableMovie_LoadTracksWithMediaType_Enum () + { + TestRuntime.AssertXcodeVersion (13, 0); + + using var url = NSUrl.FromFilename (VideoPath); + using var movie = new AVMutableMovie (url, (NSDictionary?) null, out var initError); + if (initError is not null) + Assert.Ignore ($"Could not create AVMutableMovie from test file: {initError.LocalizedDescription}"); + + var tcs = new TaskCompletionSource (); + movie.LoadTracksWithMediaType (AVMediaTypes.Video, (AVMutableMovieLoadTracksCallback) ((tracks, error) => { + tcs.TrySetResult (tracks); + })); + + Assert.That (tcs.Task.Wait (TimeSpan.FromSeconds (10)), Is.True, "Timed out"); + var result = tcs.Task.Result; + if (result is not null) { + Assert.That (result.Length, Is.GreaterThan (0), "result.Length"); + Assert.That (result [0], Is.InstanceOf (), "result[0] type"); + } + } + + [Test] + public void AVMutableMovie_LoadTracksWithMediaCharacteristic () + { + TestRuntime.AssertXcodeVersion (13, 0); + + using var url = NSUrl.FromFilename (VideoPath); + using var movie = new AVMutableMovie (url, (NSDictionary?) null, out var initError); + if (initError is not null) + Assert.Ignore ($"Could not create AVMutableMovie from test file: {initError.LocalizedDescription}"); + + var tcs = new TaskCompletionSource (); + movie.LoadTracksWithMediaCharacteristic (AVMediaCharacteristics.Visual.GetConstant ()!, (AVMutableMovieLoadTracksCallback) ((tracks, error) => { + tcs.TrySetResult (tracks); + })); + + Assert.That (tcs.Task.Wait (TimeSpan.FromSeconds (10)), Is.True, "Timed out"); + var result = tcs.Task.Result; + if (result is not null) { + Assert.That (result.Length, Is.GreaterThan (0), "result.Length"); + Assert.That (result [0], Is.InstanceOf (), "result[0] type"); + } + } + +#endif // !__TVOS__ + #endregion + + #region AVComposition + + [Test] + public void AVComposition_LoadTrack () + { + TestRuntime.AssertXcodeVersion (13, 0); + + using var url = NSUrl.FromFilename (VideoPath); + using var asset = AVAsset.FromUrl (url); + using var composition = AVMutableComposition.Create (); + + var compositionTrack = composition.AddMutableTrack (AVMediaTypes.Video.GetConstant ()!, 0); + if (compositionTrack is null) + Assert.Ignore ("Could not add track to composition"); + + var sourceTracks = asset.GetTracks (AVMediaTypes.Video); + if (sourceTracks.Length == 0) + Assert.Ignore ("No video tracks in source asset"); + + compositionTrack.InsertTimeRange (new CMTimeRange { Start = CMTime.Zero, Duration = asset.Duration }, sourceTracks [0], CMTime.Zero, out _); + + var trackId = compositionTrack.TrackID; + var tcs = new TaskCompletionSource (); + composition.LoadTrack (trackId, (AVCompositionLoadTrackCallback) ((track, error) => { + tcs.TrySetResult (track); + })); + + Assert.That (tcs.Task.Wait (TimeSpan.FromSeconds (10)), Is.True, "Timed out"); + var result = tcs.Task.Result; + Assert.That (result, Is.Not.Null, "result"); + Assert.That (result, Is.InstanceOf (), "result type"); + } + + [Test] + public void AVComposition_LoadTracksWithMediaType () + { + TestRuntime.AssertXcodeVersion (13, 0); + + using var url = NSUrl.FromFilename (VideoPath); + using var asset = AVAsset.FromUrl (url); + using var composition = AVMutableComposition.Create (); + + var compositionTrack = composition.AddMutableTrack (AVMediaTypes.Video.GetConstant ()!, 0); + if (compositionTrack is null) + Assert.Ignore ("Could not add track to composition"); + + var sourceTracks = asset.GetTracks (AVMediaTypes.Video); + if (sourceTracks.Length == 0) + Assert.Ignore ("No video tracks in source asset"); + + compositionTrack.InsertTimeRange (new CMTimeRange { Start = CMTime.Zero, Duration = asset.Duration }, sourceTracks [0], CMTime.Zero, out _); + + var tcs = new TaskCompletionSource (); + composition.LoadTracksWithMediaType (AVMediaTypes.Video.GetConstant ()!, (AVCompositionLoadTracksCallback) ((tracks, error) => { + tcs.TrySetResult (tracks); + })); + + Assert.That (tcs.Task.Wait (TimeSpan.FromSeconds (10)), Is.True, "Timed out"); + var result = tcs.Task.Result; + Assert.That (result, Is.Not.Null, "result"); + Assert.That (result!.Length, Is.GreaterThan (0), "result.Length"); + Assert.That (result [0], Is.InstanceOf (), "result[0] type"); + } + + [Test] + public void AVComposition_LoadTracksWithMediaType_Enum () + { + TestRuntime.AssertXcodeVersion (13, 0); + + using var url = NSUrl.FromFilename (VideoPath); + using var asset = AVAsset.FromUrl (url); + using var composition = AVMutableComposition.Create (); + + var compositionTrack = composition.AddMutableTrack (AVMediaTypes.Video.GetConstant ()!, 0); + if (compositionTrack is null) + Assert.Ignore ("Could not add track to composition"); + + var sourceTracks = asset.GetTracks (AVMediaTypes.Video); + if (sourceTracks.Length == 0) + Assert.Ignore ("No video tracks in source asset"); + + compositionTrack.InsertTimeRange (new CMTimeRange { Start = CMTime.Zero, Duration = asset.Duration }, sourceTracks [0], CMTime.Zero, out _); + + var tcs = new TaskCompletionSource (); + composition.LoadTracksWithMediaType (AVMediaTypes.Video, (AVCompositionLoadTracksCallback) ((tracks, error) => { + tcs.TrySetResult (tracks); + })); + + Assert.That (tcs.Task.Wait (TimeSpan.FromSeconds (10)), Is.True, "Timed out"); + var result = tcs.Task.Result; + Assert.That (result, Is.Not.Null, "result"); + Assert.That (result!.Length, Is.GreaterThan (0), "result.Length"); + Assert.That (result [0], Is.InstanceOf (), "result[0] type"); + } + + [Test] + public void AVComposition_LoadTracksWithMediaCharacteristic () + { + TestRuntime.AssertXcodeVersion (13, 0); + + using var url = NSUrl.FromFilename (VideoPath); + using var asset = AVAsset.FromUrl (url); + using var composition = AVMutableComposition.Create (); + + var compositionTrack = composition.AddMutableTrack (AVMediaTypes.Video.GetConstant ()!, 0); + if (compositionTrack is null) + Assert.Ignore ("Could not add track to composition"); + + var sourceTracks = asset.GetTracks (AVMediaTypes.Video); + if (sourceTracks.Length == 0) + Assert.Ignore ("No video tracks in source asset"); + + compositionTrack.InsertTimeRange (new CMTimeRange { Start = CMTime.Zero, Duration = asset.Duration }, sourceTracks [0], CMTime.Zero, out _); + + var tcs = new TaskCompletionSource (); + composition.LoadTracksWithMediaCharacteristic (AVMediaCharacteristics.Visual.GetConstant ()!, (AVCompositionLoadTracksCallback) ((tracks, error) => { + tcs.TrySetResult (tracks); + })); + + Assert.That (tcs.Task.Wait (TimeSpan.FromSeconds (10)), Is.True, "Timed out"); + var result = tcs.Task.Result; + Assert.That (result, Is.Not.Null, "result"); + Assert.That (result!.Length, Is.GreaterThan (0), "result.Length"); + Assert.That (result [0], Is.InstanceOf (), "result[0] type"); + } + + #endregion + } +} From 1ad0603913fbd871333fdf3a1da3fa53f742ad47 Mon Sep 17 00:00:00 2001 From: GitHub Actions Autoformatter Date: Fri, 5 Jun 2026 14:51:33 +0000 Subject: [PATCH 3/3] Auto-format source code --- src/avfoundation.cs | 10 +++---- .../AVFoundation/AVAssetLoadTracksTest.cs | 26 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/avfoundation.cs b/src/avfoundation.cs index c97568acb363..4a272feab841 100644 --- a/src/avfoundation.cs +++ b/src/avfoundation.cs @@ -5733,7 +5733,7 @@ interface AVAsset : NSCopying { } delegate void AVAssetLoadTrackCallback ([NullAllowed] AVAssetTrack track, [NullAllowed] NSError error); - delegate void AVAssetLoadTracksCallback ([NullAllowed] AVAssetTrack[] tracks, [NullAllowed] NSError error); + delegate void AVAssetLoadTracksCallback ([NullAllowed] AVAssetTrack [] tracks, [NullAllowed] NSError error); interface IAVFragmentMinding { } @@ -12760,7 +12760,7 @@ interface AVMovie_AVMovieTrackInspection { } delegate void AVMovieLoadTrackCallback ([NullAllowed] AVMovieTrack track, [NullAllowed] NSError error); - delegate void AVMovieLoadTracksCallback ([NullAllowed] AVMovieTrack[] tracks, [NullAllowed] NSError error); + delegate void AVMovieLoadTracksCallback ([NullAllowed] AVMovieTrack [] tracks, [NullAllowed] NSError error); [NoTV, iOS (13, 0)] [MacCatalyst (13, 1)] @@ -12907,7 +12907,7 @@ interface AVMutableMovie { } delegate void AVMutableMovieLoadTrackCallback ([NullAllowed] AVMutableMovieTrack track, [NullAllowed] NSError error); - delegate void AVMutableMovieLoadTracksCallback ([NullAllowed] AVMutableMovieTrack[] tracks, [NullAllowed] NSError error); + delegate void AVMutableMovieLoadTracksCallback ([NullAllowed] AVMutableMovieTrack [] tracks, [NullAllowed] NSError error); [NoTV, iOS (13, 0)] [MacCatalyst (13, 1)] @@ -13167,7 +13167,7 @@ interface AVFragmentedMovie_AVFragmentedMovieTrackInspection { } delegate void AVFragmentedMovieLoadTrackCallback ([NullAllowed] AVFragmentedMovieTrack track, [NullAllowed] NSError error); - delegate void AVFragmentedMovieLoadTracksCallback ([NullAllowed] AVFragmentedMovieTrack[] tracks, [NullAllowed] NSError error); + delegate void AVFragmentedMovieLoadTracksCallback ([NullAllowed] AVFragmentedMovieTrack [] tracks, [NullAllowed] NSError error); [iOS (13, 0), NoTV] [MacCatalyst (13, 1)] @@ -13801,7 +13801,7 @@ interface AVComposition_AVCompositionTrackInspection { } delegate void AVCompositionLoadTrackCallback ([NullAllowed] AVCompositionTrack track, [NullAllowed] NSError error); - delegate void AVCompositionLoadTracksCallback ([NullAllowed] AVCompositionTrack[] tracks, [NullAllowed] NSError error); + delegate void AVCompositionLoadTracksCallback ([NullAllowed] AVCompositionTrack [] tracks, [NullAllowed] NSError error); [MacCatalyst (13, 1)] [BaseType (typeof (AVComposition))] diff --git a/tests/monotouch-test/AVFoundation/AVAssetLoadTracksTest.cs b/tests/monotouch-test/AVFoundation/AVAssetLoadTracksTest.cs index 97102d25f0a2..0079b4716eb7 100644 --- a/tests/monotouch-test/AVFoundation/AVAssetLoadTracksTest.cs +++ b/tests/monotouch-test/AVFoundation/AVAssetLoadTracksTest.cs @@ -46,7 +46,7 @@ public void AVAsset_LoadTrackWithMediaCharacteristics () using var url = NSUrl.FromFilename (VideoPath); using var asset = AVAsset.FromUrl (url); - var tcs = new TaskCompletionSource (); + var tcs = new TaskCompletionSource (); asset.LoadTrackWithMediaCharacteristics (AVMediaCharacteristics.Visual.GetConstant ()!, (tracks, error) => { tcs.TrySetResult (tracks); }); @@ -66,7 +66,7 @@ public void AVAsset_LoadTracksWithMediaType () using var url = NSUrl.FromFilename (VideoPath); using var asset = AVAsset.FromUrl (url); - var tcs = new TaskCompletionSource (); + var tcs = new TaskCompletionSource (); asset.LoadTracksWithMediaType (AVMediaTypes.Video.GetConstant ()!, (AVAssetLoadTracksCallback) ((tracks, error) => { tcs.TrySetResult (tracks); })); @@ -86,7 +86,7 @@ public void AVAsset_LoadTracksWithMediaType_Enum () using var url = NSUrl.FromFilename (VideoPath); using var asset = AVAsset.FromUrl (url); - var tcs = new TaskCompletionSource (); + var tcs = new TaskCompletionSource (); asset.LoadTracksWithMediaType (AVMediaTypes.Video, (AVAssetLoadTracksCallback) ((tracks, error) => { tcs.TrySetResult (tracks); })); @@ -130,7 +130,7 @@ public void AVMovie_LoadTracksWithMediaType () using var url = NSUrl.FromFilename (VideoPath); using var movie = new AVMovie (url, (NSDictionary?) null); - var tcs = new TaskCompletionSource (); + var tcs = new TaskCompletionSource (); movie.LoadTracksWithMediaType (AVMediaTypes.Video.GetConstant ()!, (AVMovieLoadTracksCallback) ((tracks, error) => { tcs.TrySetResult (tracks); })); @@ -152,7 +152,7 @@ public void AVMovie_LoadTracksWithMediaType_Enum () using var url = NSUrl.FromFilename (VideoPath); using var movie = new AVMovie (url, (NSDictionary?) null); - var tcs = new TaskCompletionSource (); + var tcs = new TaskCompletionSource (); movie.LoadTracksWithMediaType (AVMediaTypes.Video, (AVMovieLoadTracksCallback) ((tracks, error) => { tcs.TrySetResult (tracks); })); @@ -173,7 +173,7 @@ public void AVMovie_LoadTracksWithMediaCharacteristic () using var url = NSUrl.FromFilename (VideoPath); using var movie = new AVMovie (url, (NSDictionary?) null); - var tcs = new TaskCompletionSource (); + var tcs = new TaskCompletionSource (); movie.LoadTracksWithMediaCharacteristic (AVMediaCharacteristics.Visual.GetConstant ()!, (AVMovieLoadTracksCallback) ((tracks, error) => { tcs.TrySetResult (tracks); })); @@ -186,7 +186,7 @@ public void AVMovie_LoadTracksWithMediaCharacteristic () } } - #endregion +#endregion #region AVMutableMovie @@ -221,7 +221,7 @@ public void AVMutableMovie_LoadTracksWithMediaType () if (initError is not null) Assert.Ignore ($"Could not create AVMutableMovie from test file: {initError.LocalizedDescription}"); - var tcs = new TaskCompletionSource (); + var tcs = new TaskCompletionSource (); movie.LoadTracksWithMediaType (AVMediaTypes.Video.GetConstant ()!, (AVMutableMovieLoadTracksCallback) ((tracks, error) => { tcs.TrySetResult (tracks); })); @@ -244,7 +244,7 @@ public void AVMutableMovie_LoadTracksWithMediaType_Enum () if (initError is not null) Assert.Ignore ($"Could not create AVMutableMovie from test file: {initError.LocalizedDescription}"); - var tcs = new TaskCompletionSource (); + var tcs = new TaskCompletionSource (); movie.LoadTracksWithMediaType (AVMediaTypes.Video, (AVMutableMovieLoadTracksCallback) ((tracks, error) => { tcs.TrySetResult (tracks); })); @@ -267,7 +267,7 @@ public void AVMutableMovie_LoadTracksWithMediaCharacteristic () if (initError is not null) Assert.Ignore ($"Could not create AVMutableMovie from test file: {initError.LocalizedDescription}"); - var tcs = new TaskCompletionSource (); + var tcs = new TaskCompletionSource (); movie.LoadTracksWithMediaCharacteristic (AVMediaCharacteristics.Visual.GetConstant ()!, (AVMutableMovieLoadTracksCallback) ((tracks, error) => { tcs.TrySetResult (tracks); })); @@ -335,7 +335,7 @@ public void AVComposition_LoadTracksWithMediaType () compositionTrack.InsertTimeRange (new CMTimeRange { Start = CMTime.Zero, Duration = asset.Duration }, sourceTracks [0], CMTime.Zero, out _); - var tcs = new TaskCompletionSource (); + var tcs = new TaskCompletionSource (); composition.LoadTracksWithMediaType (AVMediaTypes.Video.GetConstant ()!, (AVCompositionLoadTracksCallback) ((tracks, error) => { tcs.TrySetResult (tracks); })); @@ -366,7 +366,7 @@ public void AVComposition_LoadTracksWithMediaType_Enum () compositionTrack.InsertTimeRange (new CMTimeRange { Start = CMTime.Zero, Duration = asset.Duration }, sourceTracks [0], CMTime.Zero, out _); - var tcs = new TaskCompletionSource (); + var tcs = new TaskCompletionSource (); composition.LoadTracksWithMediaType (AVMediaTypes.Video, (AVCompositionLoadTracksCallback) ((tracks, error) => { tcs.TrySetResult (tracks); })); @@ -397,7 +397,7 @@ public void AVComposition_LoadTracksWithMediaCharacteristic () compositionTrack.InsertTimeRange (new CMTimeRange { Start = CMTime.Zero, Duration = asset.Duration }, sourceTracks [0], CMTime.Zero, out _); - var tcs = new TaskCompletionSource (); + var tcs = new TaskCompletionSource (); composition.LoadTracksWithMediaCharacteristic (AVMediaCharacteristics.Visual.GetConstant ()!, (AVCompositionLoadTracksCallback) ((tracks, error) => { tcs.TrySetResult (tracks); }));