在几个presentModalView/dismissModalView调用之后,AVPlayerLayer变为空白

mrg*_*ves 6 iphone avfoundation ipad ios avplayer

我有一个视频播放应用程序,AVPlayerLayer在重复显示和隐藏包含它的模态视图之后不会显示任何内容. 如果我在发生这种情况时忽略模态视图,则下一次加载通常显示正常(?!!).黑屏问题大约发生在20%的时间.

我建立一个AVMutableComposition使AVPlayerItem,但这个错误会发生,即使有只涉及单个样本.

这个问题也可以通过大量的应用程序切换和打开和关闭音乐来重现.我在我的应用程序中包含音乐控件(以及显示当前正在播放的iTunes曲目的简单视图).

这只发生在iOS 4上.它曾经发生在iOS 5上,但是当我开始回收包含AVPlayerLayer它的视图时,它运行正常.我不回收的唯一东西是AVPlayer和相关的AVPlayerItem.

这是我加载资产和构建玩家的方式:

- (void)loadAssetsFromFiles:(id)sender {
    NSLog(@"loadAssetsFromFiles called");

    assert ([assetURL2clipID count] > 0);

    self.isWaitingToLoadAssets = NO;

    composition = [AVMutableComposition new];
    videoComposition = [AVMutableVideoComposition new];
    [self releaseAssets];

    //We're going to add this asset to a composition, so we'll need to have random access available
    //WARNING: This can cause slow initial loading, so consider loading files later and as needed.
    NSDictionary *assetOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
                                                        forKey:AVURLAssetPreferPreciseDurationAndTimingKey];

    //iterate through the asset urls we know we need to load
    for (NSURL *fileURL in [assetURL2clipID allKeys])
    {
        AVURLAsset *asset = [AVURLAsset URLAssetWithURL:fileURL options:assetOptions];
        assert(asset);
        //index assets by clipID
        [assets setObject:asset forKey:[assetURL2clipID objectForKey:fileURL]];


        NSString *tracksKey = @"tracks";

        [asset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:tracksKey] completionHandler:
         ^{
             NSLog(@"an asset completed loading values for keys.");

             NSLog(@"Tracks loaded:");
             [asset.tracks enumerateObjectsUsingBlock:
                ^(AVAssetTrack *obj, NSUInteger index, BOOL *stop)
                {
                    NSLog(@"\n  mediaType: %@\n trackID: %d\n", obj.mediaType, obj.trackID);
                }];

             NSArray *metadata = [asset commonMetadata];
             for ( AVMetadataItem* item in metadata ) {
                 NSString *key = [item commonKey];
                 NSString *value = [item stringValue];
                 NSLog(@"   metadata key = %@, value = %@", key, value);
             }

             if (!viewIsActive)
             {
                 NSLog(@"An asset finished loading while the player view was inactive!  Did you make sure cancelLoading called on this asset?");
             }

             // Completion handler block.
             NSError *error = nil;

             AVKeyValueStatus status = [asset statusOfValueForKey:tracksKey error:&error];



             if (status == AVKeyValueStatusLoaded && error == nil) {

                 //if we've loaded all of our assets, it's time to build the composition and prepare the player!
                 loadedAssets++;
                 if (loadedAssets == [assets count])
                 {

                     CGSize videoSize = [asset naturalSize];
                     //every video composition needs these set
                     videoComposition.renderSize = videoSize;
                     videoComposition.frameDuration = CMTimeMake(1, 30); // 30 fps.  TODO: Set this to the framerate of one of the assets

                     //using the assets we've already got
                    [self buildCompositions];

                    self.playerItem = [AVPlayerItem playerItemWithAsset:composition];
                    self.playerItem.videoComposition = videoComposition;

                    //TODO: Adding observer stuff should be on the main thread to prevent a partial notification from happening
                    [playerItem addObserver:self forKeyPath:@"status"

                                 options:0 context:&ItemStatusContext];

                    [[NSNotificationCenter defaultCenter] addObserver:self

                                                          selector:@selector(playerItemDidReachEnd:)

                                                              name:AVPlayerItemDidPlayToEndTimeNotification

                                                            object:playerItem];

                    self.player = [AVPlayer playerWithPlayerItem:playerItem];

                    [playerView setPlayer:player];


                    [self.player addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
                    self.isObservingPlayerStatus = YES;
                 }

             } else if (error != nil) {
                 // Deal with the error appropriately.
                 NSLog(@"WARNING: An asset's tracks were not loaded, so the composition cannot be completed. Error:\n%@\nstatus of asset: %d", [error localizedDescription], status);

             }
             else
             {
                 //There was no error but we don't know what the problem was.
                 NSLog(@"WARNING: An asset's tracks were not loaded, so the composition cannot be completed. No error was reported.\nstatus of asset: %d", status);
             }

         }];
    }
}
Run Code Online (Sandbox Code Playgroud)

您看到的[self buildCompositions]函数构建了一个AVVideoComposition不透明度斜坡,但我尝试绕过它并得到同样的问题.

在分析程序时,CoreAnimation在一切正常工作时报告~45 FPS的帧速率,当空白屏幕显示其可能丑陋的头部时报告0-4 FPS.

这家伙似乎有类似的问题,但对我来说回收视图真的只能解决iOS 5的问题: 使用AVPlayer在iphone上播放许多不同的视频