2011-01-21 49 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)。