2011-01-21 82 views
2

我在這裏有一個AVAssetReader的問題,從iPod庫中獲取樣本並通過音頻隊列進行流式傳輸。我一直無法找到任何這樣的例子,所以我嘗試實現我自己的,但似乎不知何故AssetReader是「搞砸了」音頻隊列的回調函數。具體來說,它在執行copyNextSampleBuffer時會失敗,即它在尚未完成時返回null。我已經確定指針存在,所以如果有人可以幫助,這將是很好的。AVAssetReader和音頻隊列流式傳輸問題

下面是我用過的回調函數代碼。這個回調函數在AudioQueue回調沒有調用的時候「有效」。

static void HandleOutputBuffer (
     void    *playerStateH, 
     AudioQueueRef  inAQ, 
     AudioQueueBufferRef inBuffer 
     ) { 

AQPlayerState *pplayerState = (AQPlayerState *) playerStateH; 
//if (pplayerState->mIsRunning == 0) return;  



UInt32 bytesToRead = pplayerState->bufferByteSize; 
[[NSNotificationCenter defaultCenter] postNotificationName:NOTIF_callsample object:nil]; 


float * inData =(float *) inBuffer->mAudioData; 
int offsetSample = 0; 
//Loop until finish reading from the music data 
while (bytesToRead) { 

    /*THIS IS THE PROBLEMATIC LINE*/ 
    CMSampleBufferRef sampBuffer = [pplayerState->assetWrapper getNextSampleBuffer]; //the assetreader getting nextsample with copyNextSampleBuffer 

    if (sampBuffer == nil) { 
    NSLog(@"No more data to read from"); 
// NSLog(@"aro status after null %d",[pplayerState->ar status]); 
    AudioQueueStop (
     pplayerState->mQueue, 
     false 
     ); 
    pplayerState->mIsRunning = NO; 

    return; 
    } 

    AudioBufferList audioBufferList; 
    CMBlockBufferRef blockBuffer; 
    CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampBuffer, NULL, &audioBufferList, sizeof(audioBufferList), NULL, NULL, 0, &blockBuffer); 
    AudioBuffer audioBuffer = audioBufferList.mBuffers[0]; 
    memcpy(inData + (2*offsetSample),audioBuffer.mData,audioBuffer.mDataByteSize); 
    bytesToRead = bytesToRead - audioBuffer.mDataByteSize; 
    offsetSample = offsetSample + audioBuffer.mDataByteSize/8; 



} 
inBuffer->mAudioDataByteSize = offsetSample*8; 

AudioQueueEnqueueBuffer ( 
     pplayerState->mQueue, 
     inBuffer, 
     0, 
     0 
     ); 


} 

回答

0

好吧我有某種方式解決了這個奇怪的錯誤......顯然這是因爲音頻會話沒有正確設置。談論這一個缺乏文件...

2

我得到這個相同的神祕錯誤。果然,「設置」音頻會話使錯誤消失。這是我設置音頻會話的方式。

- (void)setupAudio { 
    [[AVAudioSession sharedInstance] setDelegate:self]; 
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil]; 
    NSError *activationError = nil; 
    [[AVAudioSession sharedInstance] setActive: YES error:&activationError]; 

    NSLog(@"setupAudio ACTIVATION ERROR IS %@", activationError); 
    [[AVAudioSession sharedInstance] setPreferredIOBufferDuration:0.1 error:&activationError]; 
    NSLog(@"setupAudio BUFFER DURATION ERROR IS %@", activationError); 
} 
1

從音頻會話編程指南,AVAudioSessionCategoryAmbient下:

這個範疇允許音頻從iPod,Safari和其他內置應用程序,而你的應用程序正在播放的音頻播放。

使用AVAssetReader可能使用iOS的硬件解碼器,該解碼器阻止使用AudioQueue。設置AVAudioSessionCategoryAmbient意味着音頻以軟件呈現,允許兩者同時工作 - 但是,這會影響性能/電池壽命。 (見「分類如何影響編碼和解碼」下的Audio Session Programming Guide)。