diff --git a/AVCustomEdit/AVCustomEdit/SimpleEditor.cs b/AVCustomEdit/AVCustomEdit/SimpleEditor.cs index 39c768ce..8e12d9f4 100644 --- a/AVCustomEdit/AVCustomEdit/SimpleEditor.cs +++ b/AVCustomEdit/AVCustomEdit/SimpleEditor.cs @@ -13,13 +13,19 @@ namespace AVCustomEdit public List Clips { get; set; } // array of AVURLAssets - public List ClipTimeRanges { get; set; } // array of CMTimeRanges stored in NSValues. + public List ClipTimeRanges { get; set; } public TransitionType TransitionType { get; set; } public CMTime TransitionDuration { get; set; } - public AVPlayerItem PlayerItem => new AVPlayerItem(this.composition) { VideoComposition = this.videoComposition }; + public AVPlayerItem PlayerItem { + get { + if (composition == null) + return null; + return new AVPlayerItem(this.composition) { VideoComposition = this.videoComposition }; + } + } private void BuildTransitionComposition(AVMutableComposition mutableComposition, AVMutableVideoComposition mutableVideoComposition) { @@ -30,12 +36,9 @@ namespace AVCustomEdit var transitionDuration = this.TransitionDuration; foreach (var clipTimeRange in this.ClipTimeRanges) { - if (clipTimeRange != null) - { - var halfClipDuration = clipTimeRange.CMTimeRangeValue.Duration; - halfClipDuration.TimeScale *= 2; // You can halve a rational by doubling its denominator. - transitionDuration = CMTime.GetMinimum(transitionDuration, halfClipDuration); - } + var halfClipDuration = clipTimeRange.Duration; + halfClipDuration.TimeScale *= 2; // You can halve a rational by doubling its denominator. + transitionDuration = CMTime.GetMinimum(transitionDuration, halfClipDuration); } // Add two video tracks and two audio tracks. @@ -55,16 +58,13 @@ namespace AVCustomEdit { int alternatingIndex = i % 2; // alternating targets: 0, 1, 0, 1, ... var asset = this.Clips[i]; - var clipTimeRange = this.ClipTimeRanges[i]; - - var timeRangeInAsset = clipTimeRange != null ? clipTimeRange.CMTimeRangeValue - : new CMTimeRange { Start = CMTime.Zero, Duration = asset.Duration }; + var timeRangeInAsset = this.ClipTimeRanges[i]; var clipVideoTrack = asset.TracksWithMediaType(AVMediaType.Video)[0]; - compositionVideoTracks[alternatingIndex].InsertTimeRange(timeRangeInAsset, clipVideoTrack, nextClipStartTime, out NSError error); + compositionVideoTracks[alternatingIndex].InsertTimeRange(timeRangeInAsset, clipVideoTrack, nextClipStartTime, out _); var clipAudioTrack = asset.TracksWithMediaType(AVMediaType.Audio)[0]; - compositionAudioTracks[alternatingIndex].InsertTimeRange(timeRangeInAsset, clipAudioTrack, nextClipStartTime, out error); + compositionAudioTracks[alternatingIndex].InsertTimeRange(timeRangeInAsset, clipAudioTrack, nextClipStartTime, out _); // Remember the time range in which this clip should pass through. // First clip ends with a transition. diff --git a/AVCustomEdit/AVCustomEdit/ViewController.cs b/AVCustomEdit/AVCustomEdit/ViewController.cs index c9de2130..e4779bf2 100644 --- a/AVCustomEdit/AVCustomEdit/ViewController.cs +++ b/AVCustomEdit/AVCustomEdit/ViewController.cs @@ -19,7 +19,7 @@ namespace AVCustomEdit private SimpleEditor editor; private List clips; - private List clipTimeRanges; + private List clipTimeRanges; private AVPlayer player; private AVPlayerItem playerItem; @@ -44,8 +44,8 @@ namespace AVCustomEdit base.ViewDidLoad(); this.editor = new SimpleEditor(); - this.clips = new List(); - this.clipTimeRanges = new List(); + this.clips = new List(2); + this.clipTimeRanges = new List(2); // Defaults for the transition settings. this.transitionType = TransitionType.DiagonalWipeTransition; @@ -115,8 +115,9 @@ namespace AVCustomEdit this.LoadAsset(asset2, assetKeysToLoadAndTest, dispatchGroup); // Wait until both assets are loaded - dispatchGroup.Wait(DispatchTime.Forever); - base.InvokeOnMainThread(() => this.SynchronizeWithEditor()); + dispatchGroup.Notify(DispatchQueue.MainQueue, () => { + SynchronizeWithEditor(); + }); } private void LoadAsset(AVAsset asset, string[] assetKeysToLoad, DispatchGroup dispatchGroup) @@ -124,28 +125,32 @@ namespace AVCustomEdit dispatchGroup.Enter(); asset.LoadValuesAsynchronously(assetKeysToLoad, () => { + bool add_asset = true; // First test whether the values of each of the keys we need have been successfully loaded. foreach (var key in assetKeysToLoad) { if (asset.StatusOfValue(key, out NSError error) == AVKeyValueStatus.Failed) { Console.WriteLine($"Key value loading failed for key:{key} with error: {error?.LocalizedDescription ?? ""}"); - goto bail; + add_asset = false; + break; } } if (!asset.Composable) { Console.WriteLine("Asset is not composable"); - goto bail; + add_asset = false; } - this.clips.Add(asset); - // This code assumes that both assets are atleast 5 seconds long. - var value = NSValue.FromCMTimeRange(new CMTimeRange { Start = CMTime.FromSeconds(0, 1), Duration = CMTime.FromSeconds(5, 1) }); - this.clipTimeRanges.Add(value); + if (add_asset) + { + this.clips.Add(asset); + // This code assumes that both assets are atleast 5 seconds long. + var value = new CMTimeRange { Start = CMTime.FromSeconds(0, 1), Duration = CMTime.FromSeconds(5, 1) }; + this.clipTimeRanges.Add(value); + } - bail: dispatchGroup.Leave(); }); } @@ -185,8 +190,8 @@ namespace AVCustomEdit private void SynchronizeWithEditor() { // Clips - this.SynchronizeEditorClipsWithOurClips(); - this.SynchronizeEditorClipTimeRangesWithOurClipTimeRanges(); + this.editor.Clips = new List (clips); + this.editor.ClipTimeRanges = new List (clipTimeRanges); // Transitions if (this.isTransitionsEnabled) @@ -200,36 +205,8 @@ namespace AVCustomEdit } // Build AVComposition and AVVideoComposition objects for playback - //this.editor.BuildCompositionObjectsForPlayback(true); - //this.SynchronizePlayerWithEditor(); - } - - private void SynchronizeEditorClipsWithOurClips() - { - var validClips = new List(); - foreach (var asset in this.clips) - { - if (asset != null) - { - validClips.Add(asset); - } - } - - this.editor.Clips = validClips; - } - - private void SynchronizeEditorClipTimeRangesWithOurClipTimeRanges() - { - var validClipTimeRanges = new List(); - foreach (var timeRange in this.clipTimeRanges) - { - if (timeRange != null) - { - validClipTimeRanges.Add(timeRange); - } - } - - this.editor.ClipTimeRanges = validClipTimeRanges; + this.editor.BuildCompositionObjectsForPlayback(true); + this.SynchronizePlayerWithEditor(); } #endregion