I have a working solution.
In the end I had to recycle everything but the AVAsset instances. Between each
movie run, I must destroy the AVPlayerItem, the AVPlayer, the AVPlayerLayer,
and the parent NSView since the backing layer that results from -[NSView
setWantsLayer:] disappears without so much a whimper (no exceptions in
Objective-C or C++ land), once the movie playback completes.
If this is mentioned in the programming guide for AVFoundation, I missed it
completely.
Painful lesson.
-Michael
On Dec 30, 2011, at 9:44 PM, Michael Crawford wrote:
> Little more information.
>
> I created a custom view so that I could monitor -[NSView setWantsLayer:] and
> found that there are no calls change the layer backed state of the view to
> false. The views layer simply disappears in that it is set to nil after the
> movie plays once.
>
> -Michael
>
> On Dec 29, 2011, at 9:07 AM, Michael Crawford wrote:
>
>> I'm creating a simple menu-drive movie player and have run into a problem
>> with AVPlayerLayer. The first time I attach a player with a movie the
>> playback is fine. When a second movie is selected from the menu, I never
>> receive a status of -[AVPlayerLayer readyForDisplay] set to true. If I
>> ignore this status the player will play but I only get audio playback (no
>> video). Investigating the status of the view and associated layers involved
>> shows that the layer for the layer-backed (not hosted) view becomes nil
>> after playing the first movie.
>>
>> I have no idea how this is happening. I've included the relevant snippets
>> below because I'm probably looking right at the problem and not seeing it.
>> Hopefully someone out that has a little more experience with AVFoundation
>> and can give me a clue.
>>
>> I'm using ARC.
>>
>>
>> @interface JTVMovieViewController : NSViewController
>> {
>> AVPlayerLayer* __strong playerLayer;
>> }
>>
>> @property (assign) IBOutlet id<JTVMoviewViewDelegate> delegate;
>> @property (strong) IBOutlet NSButton* homeButton;
>> @property (strong) IBOutlet NSView* playerView;
>>
>> - (void)awakeFromNib
>> {
>> playerLayer = [AVPlayerLayer layer];
>> playerLayer.frame = self.playerView.bounds;
>> playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
>> [playerLayer addObserver:self
>> forKeyPath:kReadyForDisplayKey
>> options:NSKeyValueObservingOptionNew
>> context:KVOPlayerLayerContext];
>> [self.playerView.layer addSublayer:playerLayer];
>> }
>>
>> - (void)observeValueForKeyPath:(NSString*)keyPath
>> ofObject:(id)object
>> change:(NSDictionary*)change
>> context:(void*)context
>> {
>> if ( context == KVOMoviePlaylistContext )
>> {
>> [self startPlayingNewPlayer:[self.moviePlaylist selection]];
>> }
>> else if ( context == KVOPlayerLayerContext )
>> {
>> NSLog(@"Player layer %@ ready for display.",
>> playerLayer.readyForDisplay ? @"is" : @"is not");
>>
>> if ( YES == playerLayer.readyForDisplay )
>> {
>> [playerLayer.player play];
>> }
>> }
>> }
>>
>> - (void)startPlayingNewPlayer:(AVPlayer*)player
>> {
>> [playerLayer setPlayer:player];
>>
>> if ( YES == playerLayer.readyForDisplay )
>> {
>> [player play];
>> }
>>
>> [self.delegate controllerDidBeginVideoPlayback:self];
>> }
>>
>> - (void)stopPlayback
>> {
>> [[playerLayer player] pause];
>> [[playerLayer player] seekToTime:kCMTimeZero]; // reset player
>> [playerLayer setPlayer:nil];
>> }
>>
>> (lldb) po [self playerView]
>> (NSView *) $2 = 0x000000010bf83310 <NSView: 0x10bf83310>
>> (lldb) po [[self playerView] layer]
>> (id) $3 = 0x000000010bf833d0 <_NSViewBackingLayer:0x10bf833d0; position =
>> CGPoint (0 0); bounds = CGRect (0 0; 1920 1080); delegate = <NSView:
>> 0x10bf83310>; backgroundFilters = (
>> ); filters = (
>> ); shadowColor = (null); anchorPoint = CGPoint (0 0)>
>> (lldb) po [[[self playerView] layer] sublayers]
>> (id) $4 = 0x000000010bf88880 <CALayerArray 0x10bf88880>(
>> <AVPlayerLayer:0x10bf84b50; position = CGPoint (960 540); bounds = CGRect (0
>> 0; 1920 1080); >
>> )
>>
>> (lldb) c
>> Process 96211 resuming
>> 2011-12-29 08:35:33.421 JTVideoPlayer[96211:503] Player layer is ready for
>> display.
>> << here is where I stop playback from the UI>
>> 2011-12-29 08:36:35.289 JTVideoPlayer[96211:503] Player layer is not ready
>> for display.
>> (lldb) po [self playerView]
>> (NSView *) $13 = 0x000000010bf83310 <NSView: 0x10bf83310>
>> (lldb) po [[self playerView] layer]
>> (id) $14 = 0x0000000000000000 <nil>
>> (lldb) po [playerLayer superlayer]
>> (id) $15 = 0x0000000000000000 <nil>
>> (lldb)
>>
>> -Michael
>> _______________________________________________
>>
>> Cocoa-dev mailing list ([email protected])
>>
>> Please do not post admin requests or moderator comments to the list.
>> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>>
>> Help/Unsubscribe/Update your Subscription:
>> http://lists.apple.com/mailman/options/cocoa-dev/michaelacrawford%40me.com
>>
>> This email sent to [email protected]
>
> _______________________________________________
>
> Cocoa-dev mailing list ([email protected])
>
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>
> Help/Unsubscribe/Update your Subscription:
> http://lists.apple.com/mailman/options/cocoa-dev/michaelacrawford%40me.com
>
> This email sent to [email protected]
_______________________________________________
Cocoa-dev mailing list ([email protected])
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com
This email sent to [email protected]