ios – 在进入背景并返回到前台后无法继续从AVAssetReaderOutput读取

前端之家收集整理的这篇文章主要介绍了ios – 在进入背景并返回到前台后无法继续从AVAssetReaderOutput读取前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用AVAssetReaderOutput从AVAsset读取样本,对其进行一些处理,并使用RemoteIO AU播放结果.

问题是在调用AudioOutputUnitStop暂停播放之后,在进入后台并返回到前台之后,在调用AudioOutputUnitStart之后,音频将不会再次启动.这是由于AVAssetReaderOutput的copyNextSampleBuffer方法返回的错误,它被称为渲染管道的一部分.

调用copyNextSampleBuffer之后,AVAssetReader的status属性为AVAssetReaderStatusFailed,其错误属性为Error Domain = AVFoundationErrorDomain Code = -11847“Operation Interrupted”UserInfo = 0x1d8b6100 {NSLocalizedRecoverySuggestion =停止其他操作,再次尝试,NSLocalizedDescription =操作中断}

我正在寻找一个解决方案,不会强制我重新初始化整个管道回到前台 – 希望有一个这样的解决方案,AVAssetReaders可以生存的应用程序到背景和背面…

笔记

>该应用程序有权在后台播放音频.
>我正在处理音频中断 – 将AVAudioSession设置为AVAudioSessionDelegates endInterruptionWithFlags:事件和应用程序激活时的活动.无论我是否做到这一点,没有什么不同,得到同样的错误.

一些代码

AudioPlayer

@implementation AudioPlayer
    ...
// Audio Unit Setup
AudioComponentDescription desc;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_RemoteIO;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;

AudioComponent defaultOutput = AudioComponentFindNext(NULL,&desc);

AudioComponentInstanceNew(defaultOutput,&_audioUnit);

AudioStreamBasicDescription audioFormat;
    FillOutASBDForLPCM(audioFormat,44100,2,16,false,false);

AudioUnitSetProperty(self.audioUnit,kAudioUnitProperty_StreamFormat,kAudioUnitScope_Input,kOutputBus,&audioFormat,sizeof(audioFormat));

AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = RenderCallback;
callbackStruct.inputProcRefCon = (__bridge void*)self;
AudioUnitSetProperty(self.audioUnit,kAudioUnitProperty_SetRenderCallback,&callbackStruct,sizeof(callbackStruct));

AudioUnitInitialize(self.audioUnit);

AudioReader设置

@implementation AudioReader
    ...
NSError* error = nil;
self.reader = [AVAssetReader assetReaderWithAsset:self.asset error:&error];
NSDictionary *outputSettings = ...
self.readerOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:[self.asset.tracks objectAtIndex:0] outputSettings:outputSettings];
[self.reader addOutput:self.readerOutput];
[self.reader startReading];

AudioReader渲染方法,最终由RenderCallback函数调用

-(BOOL)readChunkIntoBuffer
{
     CMSampleBufferRef sampleBuffer = [self.readerOutput copyNextSampleBuffer];
     if ( sampleBuffer == NULL )
     {
         NSLog(@"Couldn't copy next sample buffer,reader status=%d error=%@,self.reader.status,self.reader.error);
         return NO;
     }
 ...
}

解决方法

图形和AVReader基础没有连接/链接.混乱可能来自于iOS不会“背景”(hibernate)(如果它看到音频图形运行)(因为音频数据将无法生成).这就是为什么当您停止音频图形时,2-3分钟后,iOS会背景您的过程(从iOS 9开始).大概iOS会看到你的进程发生了什么,并决定你的进程应该被强制到背景(通过beginBackgroundTaskWithName:expirationHandler).

苹果公司决定不管什么原因使AVReader在进入后台模式时停止(我最好的猜测是QA).好消息是,当您的进程退出后台模式时,您可以检测并恢复,但是您需要重新启动读卡器和readerOutput.首先,当AVAssetReaderOutput的copyNextSampleBuffer返回NULL时,请检查AVErrorOperationInterrupted的AVAssetReader.error.code.

我们在这方面取消无缝恢复的方式是,当我们到达这一点时,我们首先计算出我们停留的确切时间(容易做 – 只保持已经输出的总样本的计数器).然后,您将需要重新启动AVAssetReader和AVAssetReaderOutput流程.但这是没有问题的,因为您的良好开发实践将封装在具有寻求时间作为参数的单个功能中.在那个功能中,使用AVAssetReader.timeRange来寻找那个时候你需要恢复和预先安装!

猜你在找的iOS相关文章