AVAssetReader 和 Audio Queue 流问题

Posted

技术标签:

【中文标题】AVAssetReader 和 Audio Queue 流问题【英文标题】:AVAssetReader and Audio Queue streaming problem 【发布时间】:2011-01-21 20:43:13 【问题描述】:

我在使用 AVAssetReader 从 iPod 库中获取样本并通过音频队列流式传输时遇到问题。我无法找到任何这样的示例,因此我尝试实现自己的示例,但似乎 AssetReader 在音频队列的回调函数中被“搞砸了”。具体来说,它在执行 copyNextSampleBuffer 时失败,即它在尚未完成时返回 null。我已经确保指针存在,所以如果有人能提供帮助,那就太好了。

下面是我使用过的回调函数代码。当 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
        );



【问题讨论】:

【参考方案1】:

我遇到了同样令人费解的错误。果然,“设置”音频会话使错误消失。这就是我设置音频会话的方式。

- (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);

【讨论】:

【参考方案2】:

来自音频会话编程指南,在 AVAudioSessionCategoryAmbient 下:

此类别允许在您的应用程序播放音频时播放来自 iPod、Safari 和其他内置应用程序的音频。

使用 AVAssetReader 可能会使用 iOS 的硬件解码器,这会阻止使用 AudioQueue。设置 AVAudioSessionCategoryAmbient 意味着音频在软件中呈现,允许两者同时工作 - 但是,这会对性能/电池寿命产生影响。 (参见“类别如何影响编码和解码”下的Audio Session Programming Guide)。

【讨论】:

【参考方案3】:

好的,我已经以某种方式解决了这个奇怪的错误......显然这是因为音频会话设置不正确。谈论缺乏关于这个的文档......

【讨论】:

以上是关于AVAssetReader 和 Audio Queue 流问题的主要内容,如果未能解决你的问题,请参考以下文章

第五十七篇AVAssetReader和AVAssetWrite 对视频进行编码

使用 AVAssetWriter 和 AVAssetReader 进行音频录制和播放

如何使用 AVAssetReader 和 AVAssetWriter 创建 AAC 文件?

使用 AVAssetReader 读取多个轨道

如何通过 AVAssetReader 播放声音

AVAssetReader 采样率