Iphone AVPlayerItem失败,带有AVStatusFailed和错误代码;无法解码";

Iphone AVPlayerItem失败,带有AVStatusFailed和错误代码;无法解码";,iphone,ios,avfoundation,avplayer,Iphone,Ios,Avfoundation,Avplayer,我遇到了一个奇怪的问题,希望有人能帮我 在我的iOS应用程序中,我使用MutableComposition将用户照片库中的视频和应用程序包中的音频文件结合起来,创建了一个带有自定义配乐的视频。然后,我使用AVPlayer和AVPlayerItem使用我制作的自定义视频播放器向用户播放视频 每次创建新的合成时,资产、玩家和合成都会被清除、释放,并且基本上从一个干净的初始状态开始 所有这些都可以正常工作,直到以这种方式成功创建了4个视频之后,每隔一次创建播放器的尝试都失败,出现错误无法解码。无论是我

我遇到了一个奇怪的问题,希望有人能帮我

在我的iOS应用程序中,我使用
MutableComposition
将用户照片库中的视频和应用程序包中的音频文件结合起来,创建了一个带有自定义配乐的视频。然后,我使用
AVPlayer
AVPlayerItem
使用我制作的自定义视频播放器向用户播放视频

每次创建新的合成时,资产、玩家和合成都会被清除、释放,并且基本上从一个干净的初始状态开始

所有这些都可以正常工作,直到以这种方式成功创建了4个视频之后,每隔一次创建播放器的尝试都失败,出现错误
无法解码
。无论是我正在重新创建的同一个视频,还是与视频或音频文件的大小/长度无关,只要在第五次尝试时失败,就像时钟一样。一旦失败,它将永远失败


这很奇怪,因为它只是把同一个视频解码了四次,没有问题,所以它突然失败了?所以,如果有人有线索,请告诉我。

好的,我想出了一个解决方案,我希望这对任何可能遇到类似问题的人都有帮助

在我的例子中,解决方案是在主线程上初始化AVPlayer和AVPlayerItem的资产,并确保在playerItem和player对象返回状态为“ReadyToPlay”之前,我不会创建实际的AVPlayerLayer

这被证明是很难分离的,我仍然不知道为什么它在前4次有效,然后在第5次持续失败


直到现在,我还不能真正包含代码,这不是一行甚至几个函数的问题。这是一个复杂的问题,我无法从一开始就孤立起来。不过,感谢您的评论。

在创建4个AVPlayer实例后,我遇到了相同的错误消息,但我的修复程序并不完全相同。也许这会帮助其他遇到这个问题的人

我最终发现AVP玩家并没有在我以为他们会被释放的时候被释放。在我的例子中,我将我的AVPlayer视图控制器推到导航控制器上。尽管我一次只创建一个AVPlayer实例,但当视图控制器从导航控制器弹出时,它们并没有立即释放。在清理旧的视图控制器之前,我很容易访问4个AVPlayer实例

直到我确定之前的玩家都被释放了,这个问题才得以解决。为了完整起见,我发布了AVPlayerItem、AVPlayer,并在发布之前将AVPlayerLayer上的播放器设置为零

我想知道是否有一些限制的AVPlayer实例,无意或没有。文档中的相关信息:


“多播放器层:你可以从一个AVPlayer实例创建任意多个AVPlayerLayer对象,但只有最近创建的这样的层才能在屏幕上显示任何视频内容。”

好的,各位,我直接从苹果公司得到了答案。我使用了我的一个开发者TSI生命线来问这个问题,我将总结回答

AVFoundation允许的并发视频播放器数量有限制。这是由于iOS硬件的限制。当前设备的限制为4名玩家。如果您创建了第五个播放器,您将得到“无法解码”错误。它不是对AVPlayer或AVPlayerItem实例数量的限制。相反,它是AVPlayerItem与AVPlayer的关联,AVPlayerItem创建了一个“渲染管道”,您只能使用其中的4个。例如,这会导致新的渲染管道:

AVPlayer *player = [AVPlayer playerWithPlayerItem:somePlayerItem];  
// assuming the AVPlayerItem is ready to go with an AVAsset that has been loaded
我还被警告说,您不能假设您将有4条管道可供使用。另一个应用可能正在使用一个或多个。事实上,我在iPad上看到过这种情况,但不清楚哪个应用程序在使用管道

所以,你看,这是完全没有记录的,但这就是故事。

这件事让我非常痛苦,直到我发现它,从这条线索和其他一些线索中找到了线索。我的代码中最大的一个问题是,每当我想播放视频时,我都要实例化我的视频播放器控制器。现在,它在主控制器(在本例中为my DetailViewContoller)中实例化一次:

当我想显示视频时,我调用DetailViewController的startVideoPlayback方法:

- (void) startVideoPlayback: (NSString *)videoUID
{
    videoPlayerViewController.videoUID = videoUID;
    [self presentModalViewController: videoPlayerViewController animated: YES];
}
(注意:我传递的是“videoUID”——一个唯一标识,用于在应用程序的另一部分中创建视频。)

在videoplayervewcontroller(主要是从苹果的示例中抄袭而来)中,一次性屏幕设置(初始化AVPlayer、设置工具栏等)在viewDidLoad中完成——现在只调用一次,每个视频设置都在视图中完成,然后调用prepareToPlay

- (void) prepareToPlay
{
    [self initScrubberTimer];   
    [self syncPlayPauseButtons];
    [self syncScrubber];

    NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    //*** Retrieve and play video at associated with this videoUID
    NSString *destinationPath = [documentsDirectory stringByAppendingFormat: @"/%@.mov", videoUID];
    if ([self fileExists: destinationPath]) {

        //*** Show the activity indicator spinny thing
        [pleaseWait startAnimating];
        [self setURL: [NSURL fileURLWithPath: destinationPath]];
        //*** Get things going with the first video in this session
        if (isFirst) {
            isFirst = NO;
        //*** Subseqeunt videos replace the first one
        } else {
            [self.mPlayer replaceCurrentItemWithPlayerItem: [AVPlayerItem playerItemWithURL: [NSURL fileURLWithPath: destinationPath]]];
        }
    }
}

这似乎是任何解码任务都可能导致的问题,而不仅仅是真正的玩家

当我执行后台任务从当前播放的视频中同步提取帧时,我随机遇到了这个问题

我需要在屏幕上显示4个视频,比赛条件有时会导致在视频开始播放之前开始帧提取,我将永远等待
isReadyForDisplay


不确定什么是好的恢复策略如果你不能避免这种情况,我可能会尝试
replaceCurrentItem

对不起…下面是我脑海中出现的一些问题:1。“无法解码”错误2的原因是什么。以前是否有人遇到过类似情况,如果是,解决方案是什么3。经过一些调查,我发现即使我只是简单地使用
- (void) prepareToPlay
{
    [self initScrubberTimer];   
    [self syncPlayPauseButtons];
    [self syncScrubber];

    NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    //*** Retrieve and play video at associated with this videoUID
    NSString *destinationPath = [documentsDirectory stringByAppendingFormat: @"/%@.mov", videoUID];
    if ([self fileExists: destinationPath]) {

        //*** Show the activity indicator spinny thing
        [pleaseWait startAnimating];
        [self setURL: [NSURL fileURLWithPath: destinationPath]];
        //*** Get things going with the first video in this session
        if (isFirst) {
            isFirst = NO;
        //*** Subseqeunt videos replace the first one
        } else {
            [self.mPlayer replaceCurrentItemWithPlayerItem: [AVPlayerItem playerItemWithURL: [NSURL fileURLWithPath: destinationPath]]];
        }
    }
}