2013-03-31 23 views
11

Tôi đang sử dụng AVAssetReaderOutput để đọc mẫu từ AVAsset, thực hiện một số thao tác trên chúng và phát kết quả bằng RemoteIO AU.Không thể tiếp tục đọc từ AVAssetReaderOutput sau khi chuyển sang nền và quay lại nền trước

Vấn đề là sau khi gọi AudioOutputUnitStop để tạm dừng phát lại, sau đó sau khi chuyển sang nền và quay lại nền trước, âm thanh sẽ không bắt đầu lại sau khi gọi AudioOutputUnitStart. Điều này là do lỗi được trả về từ phương pháp copyNextSampleBuffer của AVAssetReaderOutput, được gọi là một phần của đường dẫn hiển thị.

Thuộc tính status của AVAssetReader sau khi gọi copyNextSampleBufferAVAssetReaderStatusFailed, và tài sản của nó là errorLỗi miền = AVFoundationErrorDomain Mã = -11.847 "Operation Interrupted" UserInfo = 0x1d8b6100 {NSLocalizedRecoverySuggestion = Dừng các hoạt động khác và thử lại., NSLocalizedDescription = Operation Bị gián đoạn}

Tôi đang tìm một giải pháp không bắt buộc tôi phải khởi động lại toàn bộ đường ống sau khi quay lại nền trước - Hy vọng có một giải pháp như vậy, AVAssetReader s có thể tồn tại trong ứng dụng. quay lại ...

Ghi chú

  • Ứng dụng có quyền phát âm thanh ẩn.
  • Tôi đang xử lý gián đoạn âm thanh - Đặt AVAudioSession hoạt động của mình là hoạt động cả trên AVAudioSessionDelegate s endInterruptionWithFlags: sự kiện và bất cứ khi nào ứng dụng hoạt động. Không tạo ra sự khác biệt cho dù tôi có làm điều này hay không, nhận được cùng một lỗi.

Một số mã:

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 Cài đặt

@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 Method, được gọi là cuối cùng bởi hàm 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; 
    } 
... 
} 
+0

Đây có phải là loại âm thanh nén không? Một số đơn vị giải nén âm thanh phần cứng trên một số kiểu thiết bị được báo cáo không thể bị gián đoạn mà không phải khởi động lại. – hotpaw2

+0

Thú vị. Đó là để đọc một 'AVAsset' được lấy từ một' MPMediaItem', một bài hát, từ thư viện iTunes của người dùng. Vì vậy, mp3/m4a, tôi tin rằng cả hai đều được nén. Về "mô hình thiết bị" - Đây là sự cố trên iPhone 5. Có bất kỳ tham chiếu nào có sẵn cho những gì bạn mô tả không? – Danra

Trả lời

4

Đồ thị và nền tảng AVReader là không kết nối/liên kết với bất kỳ thứ gì. Sự nhầm lẫn có lẽ đến từ iOS đó sẽ không "nền" (ngủ đông) một quá trình nếu nó thấy biểu đồ âm thanh đang chạy (vì sau đó dữ liệu âm thanh sẽ không thể được tạo ra). Đó là lý do tại sao khi bạn dừng biểu đồ âm thanh, sau 2-3 phút, iOS sẽ tạo nền cho quá trình của bạn (như iOS 9). Có lẽ, iOS nhìn vào những gì đang xảy ra trong quá trình của bạn và quyết định khi nào quá trình của bạn sẽ bị buộc phải chạy nền (thông qua beginBackgroundTaskWithName:expirationHandler).

Apple devs quyết định vì lý do gì khiến AVReader dừng khi đưa vào chế độ nền (phỏng đoán tốt nhất của tôi là QA). Tin tốt là bạn có thể phát hiện và khôi phục khi quá trình thoát khỏi chế độ nền, nhưng bạn S to cần phải khởi động lại trình đọc và trình đọc của bạn một lần nữa. Đầu tiên, khi số copyNextSampleBuffer của AVAssetReaderOutput trả về NULL, hãy kiểm tra AVAssetReader.error.code cho AVErrorOperationInterrupted.

Cách chúng ta rút ra một sự phục hồi không khoảng trống ở đây là khi chúng ta đến thời điểm đó, đầu tiên chúng ta tính thời gian chính xác mà chúng ta đã dừng lại (dễ thực hiện - chỉ cần duy trì một bộ đếm của tổng số mẫu đã xuất). Sau đó, bạn S to cần phải khởi động lại luồng AVAssetReaderAVAssetReaderOutput của mình. Nhưng đó là không có vấn đề kể từ khi thực hành phát triển tốt của bạn sẽ có đóng gói rằng trong một chức năng duy nhất có một thời gian tìm kiếm như là một đối số. Trong chức năng đó, sử dụng AVAssetReader.timeRange để tìm kiếm thời gian đó bạn cần phải tiếp tục tại và mau!

3

Có điều đầu tiên tôi sẽ thử là:

Không gọi AudioOutputUnitStop? Tại sao bạn không rời khỏi biểu đồ chạy và khi âm thanh được dừng lại chỉ đơn giản là không gọi

[self.readerOutput copyNextSampleBuffer] 

Thay vào đó chỉ cần điền bộ đệm với 0 và/hoặc sử dụng một render hành động của kAudioUnitRenderAction_OutputIsSilence cho bộ đệm. Bắt đầu và dừng biểu đồ cần có thời gian và dẫn đến biểu đồ không phản hồi. Tôi không bao giờ dừng biểu đồ trong khi các ứng dụng của tôi đang chạy. (Trừ khi một số gián đoạn nghiêm trọng xảy ra) Điều này có thể giữ cho người đọc tài sản xung quanh và hạnh phúc.

Nhưng tôi có linh cảm vì AVAssetReader không được kết nối trực tiếp với biểu đồ âm thanh (bạn chỉ cần yêu cầu mẫu và đặt chúng trong bộ đệm do cuộc gọi trả lại cung cấp) vấn đề không nằm trong biểu đồ âm thanh dừng lại và khởi động lại.Vì vậy, các dòng tiếp theo của cuộc tấn công tôi sẽ cố gắng là để yêu cầu mẫu từ một AVAsset, đặt các ứng dụng vào nền và đưa nó trở lại tiền cảnh mà không cần sử dụng một biểu đồ tại tất cả. Điều này sẽ xác định xem sự cố có liên quan đến AUGraph hoặc ứng dụng đang nhập trạng thái nền hay không.

Nếu điều gì đó xảy ra buộc bạn phải xé bỏ AVAssetReader, bạn sẽ phải kết nối lại với nội dung. Vì vậy, khi bạn phải viết mã đó một tùy chọn khác tôi sẽ xem là một trong những bạn không muốn làm. Kết nối lại với AVAssetReader, tìm đến vị trí bạn rời đi và tiếp tục.

+0

Trên thực tế những gì tôi đang làm ngay bây giờ tạm dừng là chính xác như bạn đã viết, điền vào bộ đệm với 0, và cách này khi đi bg và trở lại fg và bắt đầu phát lại phát lại tiếp tục đúng. Vấn đề với cách tiếp cận này là biểu tượng "phát" vẫn còn trên thanh trạng thái. – Danra

+0

Vì vậy, bạn có nói rằng AVAssetReader được liên kết với AUGraph không? –

+0

Bạn không chắc chắn ý mình là gì? Tôi đọc từ nó trong cuộc gọi lại phát lại của AU. – Danra

Các vấn đề liên quan