Erik
Erik

Reputation: 5841

Ranges without video in AVMutableCompositionTrack and AVMutableVideoComposition issues

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

Answers (3)

Duane Fields
Duane Fields

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

Erik
Erik

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

box86rowh
box86rowh

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

Related Questions