我正在写一个iOS应用程序,可通过网络视频和音频流。
我使用AVCaptureSession使用AVCaptureVideoDataOutput抢原始视频帧和编码它们的软件使用X264 。 这个伟大的工程。
我想为音频做同样的,只是我不需要那么在音频方面的控制程度,所以我想使用内置的硬件编码器产生的AAC音频流。 这意味着使用音频转换器从音频工具箱层。 为了做到这一点,我把在AVCaptudeAudioDataOutput的音频帧的处理程序:
- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
fromConnection:(AVCaptureConnection *)connection
{
// get the audio samples into a common buffer _pcmBuffer
CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer);
CMBlockBufferGetDataPointer(blockBuffer, 0, NULL, &_pcmBufferSize, &_pcmBuffer);
// use AudioConverter to
UInt32 ouputPacketsCount = 1;
AudioBufferList bufferList;
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0].mNumberChannels = 1;
bufferList.mBuffers[0].mDataByteSize = sizeof(_aacBuffer);
bufferList.mBuffers[0].mData = _aacBuffer;
OSStatus st = AudioConverterFillComplexBuffer(_converter, converter_callback, (__bridge void *) self, &ouputPacketsCount, &bufferList, NULL);
if (0 == st) {
// ... send bufferList.mBuffers[0].mDataByteSize bytes from _aacBuffer...
}
}
在这种情况下,对于音频转换器的回调函数是非常简单的(假设数据包大小和计数是正确安装):
- (void) putPcmSamplesInBufferList:(AudioBufferList *)bufferList withCount:(UInt32 *)count
{
bufferList->mBuffers[0].mData = _pcmBuffer;
bufferList->mBuffers[0].mDataByteSize = _pcmBufferSize;
}
而对于音频转换器的设置是这样的:
{
// ...
AudioStreamBasicDescription pcmASBD = {0};
pcmASBD.mSampleRate = ((AVAudioSession *) [AVAudioSession sharedInstance]).currentHardwareSampleRate;
pcmASBD.mFormatID = kAudioFormatLinearPCM;
pcmASBD.mFormatFlags = kAudioFormatFlagsCanonical;
pcmASBD.mChannelsPerFrame = 1;
pcmASBD.mBytesPerFrame = sizeof(AudioSampleType);
pcmASBD.mFramesPerPacket = 1;
pcmASBD.mBytesPerPacket = pcmASBD.mBytesPerFrame * pcmASBD.mFramesPerPacket;
pcmASBD.mBitsPerChannel = 8 * pcmASBD.mBytesPerFrame;
AudioStreamBasicDescription aacASBD = {0};
aacASBD.mFormatID = kAudioFormatMPEG4AAC;
aacASBD.mSampleRate = pcmASBD.mSampleRate;
aacASBD.mChannelsPerFrame = pcmASBD.mChannelsPerFrame;
size = sizeof(aacASBD);
AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &aacASBD);
AudioConverterNew(&pcmASBD, &aacASBD, &_converter);
// ...
}
这看起来非常简单的只是它不工作 。 一旦AVCaptureSession正在运行时,所述音频转换器(具体AudioConverterFillComplexBuffer)返回一个“hwiu”(硬件在使用中)错误。 如果会话停止转换工作正常,但我不能捕获任何...
我不知道是否有一种方式来获得一个AAC流出来AVCaptureSession的。 我正在考虑的选项包括:
不知怎的,使用AVAssetWriterInput编码音频样本插入到AAC,然后(不通过AVAssetWriter,这将只写入一个文件)以某种方式获取编码的数据包。
重新组织我的应用程序,使其只在视频方面采用AVCaptureSession并使用音频队列在音频方面。 这将使流量控制(启动和停止录音,响应中断)更复杂,我担心这样可能会导致音频与视频之间synching问题。 此外,它只是似乎并不像一个很好的设计。
有谁知道,如果得到AAC出AVCaptureSession是可能的? 我一定要在这里使用音频队列? 难道这让我进入synching或控制的问题?