2015-07-15 7 views
2

Я пишу приложение для 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 не не сохраняется, так нет необходимости, чтобы освободить его. Однако теперь я получаю ужасную статичность в аудио.

У кого-нибудь есть идея, как решить эту проблему?

Спасибо, Ozgur

ответ

1

Один из способов это обычно делается это, чтобы скопировать все данные выборки аудио из unretained буфера в свой собственный (предварительно выделенной и нераспределенной, безблокировочного) кольцевой буфер FIFO. Затем проигнорируйте неиспользуемый буфер, поскольку он будет выпущен в какой-то момент. Используйте аудиоданные в своем круговом буфере.

+0

Во второй (альтернативной) реализации getAudioBufferDataFromCMSampleBufferRef я использовал CMBlockBufferCopyDataBytes (_blockBuffer, 0, audioBufferByteSize, inputBuffer.mData); чтобы скопировать blockBuffer в свой собственный буфер inputBuffer.mData. Однако в этом случае в звуке присутствует сильная статичность. inputBuffer имеет тип AudioBuffer. Вы хоть представляете, как я могу избавиться от статики? – ozguronur

+0

Является ли ваш собственный буфер замкнутым кольцевым буфером в несколько раз больше, чем один AudioBuffer? Если нет, вы можете перезаписать данные, прежде чем закончите использовать их. – hotpaw2

+0

Это путь, особенно если данные кодируются. Кодексу потребуется определенное количество кадров для каждого пакета. Если осталось недостаточно образцов для завершения пакета, то AudioConverterFillComplexBuffer должен выйти из строя, а затем свернуть оставшиеся образцы в следующий пакет, если в вашем буфере больше образцов. – dave234

 Смежные вопросы

  • Нет связанных вопросов^_^