2015-12-04 136 views
0

我使用AVAssetwriter錄製視頻/音頻,並希望能夠編寫無聲的Sample Buffers。我並不是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是音頻設備重新連接後的第一個採樣緩衝區。這給我提供了我需要填補的差距多長時間的信息。 LastAudioDisconnect始終保存來自寫入的最後一個音頻採樣緩衝區的演示時間戳。

隨着衛隊的malloc啓用了程序崩潰:CrashIfClientProvidedBogusAudioBufferList

編輯: 隨着衛隊malloc的殘疾人,我能夠多次重新連接音頻設備,同時記錄,當我停止錄製,差距有沒有問題。

接下來的問題是,我只有幾分鐘的時間來重新連接設備後停止錄製,因爲AVAssetWriter隨機失敗,錯誤代碼爲11800(AVErrorUnknown)。

+0

你完成了嗎? @Legi謝謝 –

回答

0

錯誤是因爲您創建的CMSampleBuffer太長。

創建的CMSampleBuffer應該與用實況音頻填充的前進樣本緩衝區的長度相同(包含相同數量的樣本)。如有必要,您可以創建多個靜音緩衝區,並以與實時音頻緩衝區相同的速率傳輸它們。

+0

感謝您的回答。爲了測試它,我創建了一個名爲lastAudioNumSamples的新變量,用於存儲來自最後一個樣本緩衝區的信息,該樣本緩衝區在我的示例中已寫入並設置了numSamples = lastAudioNumSamples。 隨着這種變化,它是隨機的,不管它是否每次我在記錄時重新連接音頻設備時崩潰。感覺它越來越好。我編輯了我的問題,添加了一些關於我之前嘗試的更多信息。 – Legi