Używam AVAssetReaderOutput
do odczytywania próbek z AVAsset
, do przetwarzania na nich i odtwarzania wyniku za pomocą jednostki AU RemoteIO.Nie można kontynuować odczytu z AVAssetReaderOutput po przejściu do tła i z powrotem na pierwszy plan
Problem polega na tym, że po wywołaniu AudioOutputUnitStop
, aby wstrzymać odtwarzanie, po przejściu do tła i z powrotem do pierwszego planu dźwięk nie rozpocznie się ponownie po wywołaniu AudioOutputUnitStart
. Jest to spowodowane błędem zwróconym przez metodę z AVAssetReaderOutput
, która jest wywoływana jako część potoku renderowania.
Obiekt status
z AVAssetReader
po wywołaniu copyNextSampleBuffer
jest AVAssetReaderStatusFailed
, a jego error
nieruchomość jest Error Code AVFoundationErrorDomain Domain = -11847 = "Operacja przerwana" UserInfo = 0x1d8b6100 {NSLocalizedRecoverySuggestion = Zatrzymaj innych operacji i spróbuj ponownie., NSLocalizedDescription = Operacja przerwany}
szukam rozwiązania, które nie zmusi mnie do ponownego zainicjowania całego rurociągu po powrocie na pierwszym planie - Licząc jest takie rozwiązanie, że AVAssetReader
s może przetrwać aplikację zamiar tle i wróć ...
Uwagi
- Aplikacja jest uprawniony do odtwarzania dźwięku w tle.
- Zajmuję się przerwaniami audio - ustawiam
AVAudioSession
jako aktywną zarówno na zdarzenieAVAudioSessionDelegate
s, jak i za każdym razem, gdy aplikacja staje się aktywna. Nie ma znaczenia, czy to zrobię, czy nie, otrzymując ten sam błąd.
Niektóre kodu:
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, 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, kAudioUnitScope_Input, kOutputBus, &callbackStruct, sizeof(callbackStruct));
AudioUnitInitialize(self.audioUnit);
AudioReader Konfiguracja
@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 Render metodzie zwanej ostatecznie przez funkcję 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;
}
...
}
Czy jest to skompresowany typ audio? Niektóre ze sprzętowych dekompresorów dźwięku w niektórych modelach urządzeń nie mogą zostać przerwane bez konieczności ponownego uruchamiania. – hotpaw2
Interesujące. Jest przeznaczony do odczytu "zestawu AVA" pobranego z "MPMediaItem", utworu z biblioteki iTunes użytkownika. Więc mp3/m4a, uważam, że oba są skompresowane. Odnośnie "modeli urządzeń" - jest to problem na iPhonie 5. Czy istnieje jakieś odniesienie do tego, co opisujesz? – Danra