Reputation: 5841
I create a composition with several video clips, i also add some empty ranges where I show title screens with CoreAnimation.
|--Video1--|--NoVideo(AVsyncLayer)--|--Video2--|
Etc... Which all works fine, the problem comes when I start using: AVMutableVideoComposition, AVMutableVideoCompositionInstruction and AVMutableVideoCompositionLayerInstruction which I have to do to rotate videos properly.
|--Video1--|--NoVideo(AVsyncLayer)--|
Works fine in my AVPlayer, but if I instead do:
|--NoVideo(AVsyncLayer)--|--Video1--|
The application crashes the next time I push a new view controller, or pop the current view controller in my Navigation Controller stack. Sometimes with a memory warning sometimes without it, but according to instruments I only allocated 1.5Mb.
I've watched the Working With Media in AVFoundation from last years WWDC several times, and the only thing I can think of is that the comment
AVMutableVideoCompositionInstruction must not overlap or contain gaps.
Which it really doesn't. I have instructions for the full duration of the composition. But there are gaps in the AVMutableCompositionTrack (my video track) where I don't plan to show video, but only the CoreAnimation layer.
Have anyone else experienced similar issues?
Upvotes: 1
Views: 2304
Reputation: 1341
Expanding on Erik's solution, here's what I did. I create a very brief black movie clip, and add this to the tail end of the empty time range. It seems to work fine, though I'd hope a more elegant solution exists. (Note that in my code TMAVCompositionTrack is just a wrapper that holds AVMutableCompositionTrack's for audio and video, along with some other things.
- (void)createEmptySpaceOnTrack:(TMAVCompositionTrack*)avtrack timeRange:(CMTimeRange)timeRangeOfShot {
[avtrack.videoCompositionTrack insertEmptyTimeRange:timeRangeOfShot];
[avtrack.audioCompositionTrack insertEmptyTimeRange:timeRangeOfShot];
// there is a bug where emptyness is trimmed out, so put a brief burst of video blackness at the end of the "emptyness"
NSURL* assetURL = [[NSBundle mainBundle] URLForResource:@"blackness" withExtension:@"mov"];
AVAsset* asset = [AVURLAsset URLAssetWithURL:assetURL options:@{ AVURLAssetPreferPreciseDurationAndTimingKey:@(YES) }];
AVAssetTrack *clipVideoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
CMTimeRange timeRangeInAsset = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(0.01, 600));
CMTime tailEnd = CMTimeSubtract(CMTimeRangeGetEnd(timeRangeOfShot), timeRangeInAsset.duration);
[avtrack.videoCompositionTrack insertTimeRange:timeRangeInAsset ofTrack:clipVideoTrack atTime:tailEnd error:nil];
}
Upvotes: 1
Reputation: 5841
insert empty time range works in some cases, but we found it wasn't good enough as it broke when we let the user rewind/fast-forward and change on the time bar. To solve this we added a black video clip when nothing else was showing.
Upvotes: 0
Reputation: 3415
You need to use the InsertEmptyTimeRange method on the track so that there are no gaps on the track.
See Extending an AVMutableComposition for some more info.
Upvotes: 1