0

Я записываю видео/аудио с помощью AVAssetwriter и хочу иметь возможность писать тихие буферы для проб. Я не так разбираюсь в CoreAudio, поэтому у меня проблемы с рабочим решением.Написание тишины CMSampleBuffer вызывает сбой: CrashIfClientProvidedBogusAudioBufferList

Идея состоит в том, чтобы сохранять видеозапись, когда аудиоустройство отключено до его повторного подключения. Проблема заключается в том, что AVFoundation каким-то образом нажимает аудио на передний план, поэтому полученный файл видео не синхронизирован.

Моя текущая реализация пытается создать пустой/бесшумный CMSampleBuffer для размещения между сегментами, где нет подключенного аудиоустройства.

if (audioOutput == captureOutput && audioWriterInput.readyForMoreMediaData) { 
    if (needToFillAudioGap) { 

     CMTime temp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer); 
     CMItemCount numSamples = temp.value - lastAudioDisconnect.value; 
     OSStatus status; 
     CMBlockBufferRef bbuf = NULL; 
     CMSampleBufferRef sbuf = NULL; 
     int nchans = 2; 
     size_t buflen = numSamples * nchans * sizeof(float); 


     NSMutableData* data = [NSMutableData dataWithLength:buflen]; 
     void* samples = [data mutableBytes]; 
     status = CMBlockBufferCreateWithMemoryBlock(
                kCFAllocatorDefault, 
                samples, 
                buflen, 
                kCFAllocatorNull, 
                NULL, 
                0, 
                buflen, 
                0, 
                &bbuf); 
     if (status != noErr) { 
      NSLog(@"CMBlockBufferCreateWithMemoryBlock error: %d", (int)status); 
      return; 
     } 
     CMBlockBufferRef blockBufferContiguous; 
     status = CMBlockBufferCreateContiguous(kCFAllocatorDefault, 
               bbuf, 
               kCFAllocatorNull, 
               NULL, 
               0, 
               buflen, 
               0, 
               &blockBufferContiguous); 

     CFRelease(bbuf); 
     if(status != noErr) 
     { 
      printf("CMBlockBufferCreateContiguous failed with error %d\n", (int)status); 
      return; 
     } 

     status = CMAudioSampleBufferCreateReadyWithPacketDescriptions(kCFAllocatorDefault, blockBufferContiguous, CMSampleBufferGetFormatDescription(sampleBuffer), numSamples, lastAudioDisconnect, NULL, &sbuf); 
     CFRelease(blockBufferContiguous); 

     if (status != noErr) { 
      NSLog(@"CMSampleBufferCreate error: %d", (int)status); 
      return; 
     } 
     BOOL r = [audioWriterInput appendSampleBuffer:sbuf]; 
     if (!r) { 
      NSLog(@"appendSampleBuffer error: %d", (int)status); 
      return; 
     } 
     CFRelease(sbuf); 
     NSLog(@"Filling Audio Gap"); 
     needToFillAudioGap = false; 
    } else { 

     if ([audioWriterInput appendSampleBuffer:sampleBuffer]) 
      lastAudioDisconnect = CMSampleBufferGetPresentationTimeStamp(sampleBuffer); 
    } 
} 

sampleBuffer на вершине является первым samplebuffer после того, как аудиоустройство повторного подключения. Это дает мне информацию о том, как долго пробел, который я должен заполнить, должен быть. LastAudioDisconnect всегда содержит временную метку презентации из последнего записанного буфера аудио.

С Guard таНос включена программа падает с: CrashIfClientProvidedBogusAudioBufferList

EDIT: С Guard Malloc отключен я могу восстановить аудиоустройство несколько раз во время записи, и когда я остановить запись, разрыв там без проблем ,

Проблема заключается в том, что у меня есть только пара минут, чтобы остановить запись после повторного подключения устройства, потому что AVAssetWriter случайно не работает с кодом 11800 (AVErrorUnknown).

+0

Вы сделали это? @Legi спасибо –

ответ

0

Ошибка в том, что ваш созданный CMSampleBuffer слишком длинный.

Созданный CMSampleBuffer должен иметь одинаковую длину (содержащую то же количество выборок) в качестве буферов пробной обработки, которые заполняются живым звуком. Вы можете создать несколько тихих буферов, если это необходимо, и доставить их с той же скоростью, что и звуковые буферы.

+0

Спасибо за ваш ответ. Чтобы проверить это, я создал новую переменную, называемую lastAudioNumSamples, чтобы сохранить эту информацию из последнего образца буфера, который был написан, и в моем примере установить numSamples = lastAudioNumSamples. С этим изменением случайным является случай, если он сбой каждый раз, когда я снова подключаю аудиоустройство во время записи. Похоже, что становится все лучше. Я редактировал свой вопрос, чтобы добавить немного больше информации о моих предыдущих попытках. – Legi