从麦克风捕获音频时,我陷入了内存泄漏或音频中的过多静电之间
I am stuck between either a memory leak or excessive static in Audio while capturing audio from microphone
我正在编写一个 iPhone 应用程序,我需要从麦克风中捕获音频并将其以 AAC 格式流式传输到流式传输服务器。所以我首先捕获音频然后使用
AudioConverterFillComplexBuffer
将音频转换为 AAC 的方法。
下面是代码
- (void) captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
NSArray *audioChannels = connection.audioChannels;
if (audioChannels == nil || [audioChannels count]==0) {
// NSLog(@"We have Video Frame");
[_encoder encodeFrame:sampleBuffer];
}else{
// NSLog(@"We have Audio Frame");
if (hasAudio) {
CMTime prestime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
double dPTS = (double)(prestime.value) / prestime.timescale;
[self getAudioBufferDataFromCMSampleBufferRef:sampleBuffer];
// describe output data buffers into which we can receive data.
AudioBufferList outputBufferList;
outputBufferList.mNumberBuffers = 1;
outputBufferList.mBuffers[0].mNumberChannels = _aacASBD.mChannelsPerFrame;
outputBufferList.mBuffers[0].mDataByteSize = _aacBufferSize;
outputBufferList.mBuffers[0].mData = _aacBuffer;
OSStatus st = AudioConverterFillComplexBuffer(_converter, &putPcmSamplesInBufferList, (__bridge void *) self, &_numOutputPackets, &outputBufferList, NULL);
if (0 == st) {
[_rtsp onAudioData:_aacBuffer :outputBufferList.mBuffers[0].mDataByteSize :dPTS];
}else{
NSLog(@"Error converting Buffer");
NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:st userInfo:nil];
NSLog([self OSStatusToStr :st] );
char * str = new char[3];
FormatError(str, st);
}
if (_blockBuffer) // Double check that what you are releasing actually exists!
{
CFRelease(_blockBuffer);
}
}
}
代码为
getAudioBufferDataFromCMSampleBufferRef
如下
- (AudioBuffer) getAudioBufferDataFromCMSampleBufferRef: (CMSampleBufferRef)audioSampleBuffer{
AudioBufferList audioBufferList;
OSStatus err = CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(audioSampleBuffer, NULL, &audioBufferList, sizeof(audioBufferList), NULL, NULL, 0, &_blockBuffer);
AudioBuffer audioBuffer ;
if (!err && _blockBuffer && audioBufferList.mBuffers[0].mData && (audioBufferList.mBuffers[0].mDataByteSize > 0))
{
for( int y=0; y<audioBufferList.mNumberBuffers; y++ )
{
audioBuffer = audioBufferList.mBuffers[y];
break;
}
}
inputBuffer.mData=audioBuffer.mData;
inputBuffer.mDataByteSize=audioBuffer.mDataByteSize;
inputBuffer.mNumberChannels=1;
return audioBuffer;
}
在上面的代码版本中,我得到一个 BAD_ACCESS 错误。相反,如果我删除了释放 blockBuffer 的代码,就会出现内存泄漏,应用程序最终会因为内存压力而终止。
如果我不保留blockBuffer而写
的代码
getAudioBufferDataFromCMSampleBufferRef
与下面给出的不同
- (AudioBuffer) getAudioBufferDataFromCMSampleBufferRef: (CMSampleBufferRef)audioSampleBuffer
{
_blockBuffer = CMSampleBufferGetDataBuffer(audioSampleBuffer);
int audioBufferByteSize = CMSampleBufferGetTotalSampleSize(audioSampleBuffer);
CMBlockBufferCopyDataBytes(_blockBuffer,0,audioBufferByteSize,inputBuffer.mData);
inputBuffer.mDataByteSize=audioBuffer.mDataByteSize;
inputBuffer.mNumberChannels=1;
}
在此版本中,blockbuffer 未保留,因此无需释放它。但是现在我在音频中听到了可怕的静电。
有人知道如何解决这个问题吗?
谢谢,
厄兹古尔
一种常见的方法是将所有音频样本数据从未保留的缓冲区复制到您自己的(预分配和保留的,无锁的)循环 fifo 缓冲区中。然后忽略未保留的缓冲区,因为它会在某个时候被释放。使用您自己的循环缓冲区中的音频数据。
我正在编写一个 iPhone 应用程序,我需要从麦克风中捕获音频并将其以 AAC 格式流式传输到流式传输服务器。所以我首先捕获音频然后使用
AudioConverterFillComplexBuffer
将音频转换为 AAC 的方法。
下面是代码
- (void) captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
NSArray *audioChannels = connection.audioChannels;
if (audioChannels == nil || [audioChannels count]==0) {
// NSLog(@"We have Video Frame");
[_encoder encodeFrame:sampleBuffer];
}else{
// NSLog(@"We have Audio Frame");
if (hasAudio) {
CMTime prestime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
double dPTS = (double)(prestime.value) / prestime.timescale;
[self getAudioBufferDataFromCMSampleBufferRef:sampleBuffer];
// describe output data buffers into which we can receive data.
AudioBufferList outputBufferList;
outputBufferList.mNumberBuffers = 1;
outputBufferList.mBuffers[0].mNumberChannels = _aacASBD.mChannelsPerFrame;
outputBufferList.mBuffers[0].mDataByteSize = _aacBufferSize;
outputBufferList.mBuffers[0].mData = _aacBuffer;
OSStatus st = AudioConverterFillComplexBuffer(_converter, &putPcmSamplesInBufferList, (__bridge void *) self, &_numOutputPackets, &outputBufferList, NULL);
if (0 == st) {
[_rtsp onAudioData:_aacBuffer :outputBufferList.mBuffers[0].mDataByteSize :dPTS];
}else{
NSLog(@"Error converting Buffer");
NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:st userInfo:nil];
NSLog([self OSStatusToStr :st] );
char * str = new char[3];
FormatError(str, st);
}
if (_blockBuffer) // Double check that what you are releasing actually exists!
{
CFRelease(_blockBuffer);
}
}
}
代码为 getAudioBufferDataFromCMSampleBufferRef 如下
- (AudioBuffer) getAudioBufferDataFromCMSampleBufferRef: (CMSampleBufferRef)audioSampleBuffer{
AudioBufferList audioBufferList;
OSStatus err = CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(audioSampleBuffer, NULL, &audioBufferList, sizeof(audioBufferList), NULL, NULL, 0, &_blockBuffer);
AudioBuffer audioBuffer ;
if (!err && _blockBuffer && audioBufferList.mBuffers[0].mData && (audioBufferList.mBuffers[0].mDataByteSize > 0))
{
for( int y=0; y<audioBufferList.mNumberBuffers; y++ )
{
audioBuffer = audioBufferList.mBuffers[y];
break;
}
}
inputBuffer.mData=audioBuffer.mData;
inputBuffer.mDataByteSize=audioBuffer.mDataByteSize;
inputBuffer.mNumberChannels=1;
return audioBuffer;
}
在上面的代码版本中,我得到一个 BAD_ACCESS 错误。相反,如果我删除了释放 blockBuffer 的代码,就会出现内存泄漏,应用程序最终会因为内存压力而终止。
如果我不保留blockBuffer而写
的代码 getAudioBufferDataFromCMSampleBufferRef
与下面给出的不同
- (AudioBuffer) getAudioBufferDataFromCMSampleBufferRef: (CMSampleBufferRef)audioSampleBuffer
{
_blockBuffer = CMSampleBufferGetDataBuffer(audioSampleBuffer);
int audioBufferByteSize = CMSampleBufferGetTotalSampleSize(audioSampleBuffer);
CMBlockBufferCopyDataBytes(_blockBuffer,0,audioBufferByteSize,inputBuffer.mData);
inputBuffer.mDataByteSize=audioBuffer.mDataByteSize;
inputBuffer.mNumberChannels=1;
}
在此版本中,blockbuffer 未保留,因此无需释放它。但是现在我在音频中听到了可怕的静电。
有人知道如何解决这个问题吗?
谢谢, 厄兹古尔
一种常见的方法是将所有音频样本数据从未保留的缓冲区复制到您自己的(预分配和保留的,无锁的)循环 fifo 缓冲区中。然后忽略未保留的缓冲区,因为它会在某个时候被释放。使用您自己的循环缓冲区中的音频数据。