마이크에서 오디오를 캡처하여 AAC 형식의 스트리밍 서버로 스트리밍해야하는 iPhone 앱을 작성 중입니다. 그래서 먼저 오디오를 캡처 한 다음
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;
}
이 버전에서는 블록 버퍼가 유지되지 않으므로 해제 할 필요가 없습니다. 그러나 이제 나는 오디오에서 끔찍한 정적을 얻습니다.
이 문제를 해결하는 방법에 대한 아이디어가 있습니까?
고마워, Ozgur
한 가지 방법은 일반적으로 보유되지 않은 버퍼의 모든 오디오 샘플 데이터를 자체 (사전 할당 및 보유, 잠금없는) 원형 fifo 버퍼로 복사하는 것입니다. 그런 다음 어느 시점에서 해제되므로 보유되지 않은 버퍼를 무시하십시오. 자신의 원형 버퍼에서 오디오 데이터를 사용하십시오.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다