2017-10-24 79 views
10

Bir AVCaptureAudioDataOutputSampleBufferDelegate içinde captureOutput tarafından döndürülen bir CMSampleBuffer kopyasını oluşturmaya çalışıyorum.Ses CMSampleBuffer Kopyası

Sorun şu ki, 'da uzun süre tutulduktan sonra çerçevelerim captureOutput:didOutputSampleBuffer:fromConnection: delege yönteminden geliyor.

Açıkçası, daha fazla işlem için gelen arabelleklerin derin kopyalarını oluşturmam gerekiyor. Ayrıca CMSampleBufferCreateCopy'un sadece sığ kopya oluşturduğunu biliyorum.

birkaç ilişkili sorular SO üzerinde istendi vardır:

Ama bunların hiçbiri 12 parametreleri ile doğru CMSampleBufferCreate fonksiyonu kullanmak için bana yardımcı olur:

CMSampleBufferRef copyBuffer; 

    CMBlockBufferRef data = CMSampleBufferGetDataBuffer(sampleBuffer); 
    CMFormatDescriptionRef formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer); 
    CMItemCount itemCount = CMSampleBufferGetNumSamples(sampleBuffer); 

    CMTime duration = CMSampleBufferGetDuration(sampleBuffer); 
    CMTime presentationStamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer); 
    CMSampleTimingInfo timingInfo; 
    timingInfo.duration = duration; 
    timingInfo.presentationTimeStamp = presentationStamp; 
    timingInfo.decodeTimeStamp = CMSampleBufferGetDecodeTimeStamp(sampleBuffer); 


    size_t sampleSize = CMBlockBufferGetDataLength(data); 
    CMBlockBufferRef sampleData; 

    if (CMBlockBufferCopyDataBytes(data, 0, sampleSize, &sampleData) != kCMBlockBufferNoErr) { 
    VLog(@"error during copying sample buffer"); 
    } 

    // Here I tried data and sampleData CMBlockBuffer instance, but no success 
    OSStatus status = CMSampleBufferCreate(kCFAllocatorDefault, data, isDataReady, nil, nil, formatDescription, itemCount, 1, &timingInfo, 1, &sampleSize, &copyBuffer); 

    if (!self.sampleBufferArray) { 
    self.sampleBufferArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 
    //EXC_BAD_ACCESS crash when trying to add sampleBuffer to the array 
    CFArrayAppendValue(self.sampleBufferArray, copyBuffer); 
    } else { 
    CFArrayAppendValue(self.sampleBufferArray, copyBuffer); 
    } 

Ses CMSampleBuffer'ı nasıl kopyalıyorsunuz? Cevaplarınızda herhangi bir dili (hızlı/objektif-c) kullanmaktan çekinmeyin.

+0

Derin bir kopyasına ihtiyacınız olduğu aşikar mı? 'CMSampleBufferCreateCopy' kullandığınızda ne olur? CMSampleBufferCopySampleBufferForRange, size derin bir kopyasını verebilir mi? Daha fazla işlem için gerçekten CMSampleBuffer'a ihtiyacınız var mı? Kendi işleminizi yapıyorsanız, length + işaretçisi daha uygun olabilir. –

+0

@RhythmicFistman Evet, 'CMSampleBufferCreateCopy' kullanırsam ve kopyalanan örneği 'CFArray' içinde 1 saniyeden fazla tutarsa, didOutputSampleBuffer 'çağrılmayı durdurur. Bu [soru] ile kolayca çoğaltabilirsiniz (https://stackoverflow.com/questions/30850676/avcaptureoutput-didoutputsamplebuffer-stops-getting-called). Davranışı "CMSampleBufferCopySampleBufferForRange" ile kontrol edip sizi güncellerim. –

+0

Ah, tamam, bu arabellekleri temsilci geri aramalarını engeller önemli bilgilerdir. Yukarıdaki kodun çalıştırılabilir sürümüne bir bağlantınız var mı? –

cevap

6

Sonunda uyguladığım bir çalışma çözümü. Bu snippet'i Apple Developer Teknik desteğine gönderdim ve gelen örnek ara belleğini kopyalamanın doğru bir yolu olup olmadığını kontrol etmelerini istedim. Temel fikir, AudioBufferList numaralı kopyayı kopyalayıp, bir CMSampleBuffer oluşturun ve bu örnek için AudioBufferList'u ayarlayın.

 AudioBufferList audioBufferList; 
     CMBlockBufferRef blockBuffer; 
     //Create an AudioBufferList containing the data from the CMSampleBuffer, 
     //and a CMBlockBuffer which references the data in that AudioBufferList. 
     CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBuffer, NULL, &audioBufferList, sizeof(audioBufferList), NULL, NULL, 0, &blockBuffer); 
     NSUInteger size = sizeof(audioBufferList); 
     char buffer[size]; 

     memcpy(buffer, &audioBufferList, size); 
     //This is the Audio data. 
     NSData *bufferData = [NSData dataWithBytes:buffer length:size]; 

     const void *copyBufferData = [bufferData bytes]; 
     copyBufferData = (char *)copyBufferData; 

     CMSampleBufferRef copyBuffer = NULL; 
     OSStatus status = -1; 

     /* Format Description */ 

     AudioStreamBasicDescription audioFormat = *CMAudioFormatDescriptionGetStreamBasicDescription((CMAudioFormatDescriptionRef) CMSampleBufferGetFormatDescription(sampleBuffer)); 

     CMFormatDescriptionRef format = NULL; 
     status = CMAudioFormatDescriptionCreate(kCFAllocatorDefault, &audioFormat, 0, nil, 0, nil, nil, &format); 

     CMFormatDescriptionRef formatdes = NULL; 
     status = CMFormatDescriptionCreate(NULL, kCMMediaType_Audio, 'lpcm', NULL, &formatdes); 
     if (status != noErr) 
     { 
     NSLog(@"Error in CMAudioFormatDescriptionCreator"); 
     CFRelease(blockBuffer); 
     return; 
     } 

     /* Create sample Buffer */ 
     CMItemCount framesCount = CMSampleBufferGetNumSamples(sampleBuffer); 
     CMSampleTimingInfo timing = {.duration= CMTimeMake(1, 44100), .presentationTimeStamp= CMSampleBufferGetPresentationTimeStamp(sampleBuffer), .decodeTimeStamp= CMSampleBufferGetDecodeTimeStamp(sampleBuffer)}; 

     status = CMSampleBufferCreate(kCFAllocatorDefault, nil , NO,nil,nil,format, framesCount, 1, &timing, 0, nil, &copyBuffer); 

     if(status != noErr) { 
     NSLog(@"Error in CMSampleBufferCreate"); 
     CFRelease(blockBuffer); 
     return; 
     } 

     /* Copy BufferList to Sample Buffer */ 
     AudioBufferList receivedAudioBufferList; 
     memcpy(&receivedAudioBufferList, copyBufferData, sizeof(receivedAudioBufferList)); 

     //Creates a CMBlockBuffer containing a copy of the data from the 
     //AudioBufferList. 
     status = CMSampleBufferSetDataBufferFromAudioBufferList(copyBuffer, kCFAllocatorDefault , kCFAllocatorDefault, 0, &receivedAudioBufferList); 
     if (status != noErr) { 
     NSLog(@"Error in CMSampleBufferSetDataBufferFromAudioBufferList"); 
     CFRelease(blockBuffer); 
     return; 
     } 

Kod Düzeyinde Destek cevap:

Bu kod Tamam görünüyor (bazı ek hata denetimi eklemek isteyeceksiniz rağmen). Ses yakalamak ve kaydetmek için AVCaptureAudioDataOutput temsilcisi captureOutput:didOutputSampleBuffer:fromConnection: yöntemini uygulayan bir uygulamada başarıyla test ettim. Bu derin kopya kodunu kullanırken yakalanan ses, sağlanan örnek tamponu (derin kopya olmadan) kullanarak aldığımla aynı gibi görünüyor.

Apple Geliştirici Teknik Destek

+0

Bu harika, ancak video örnekleri ile benzer bir sorunla karşılaşıyorum (örnek arabelleklerini korumam gerekiyor). Bunun için nasıl uygulanacağına dair bir ipucunuz var mı? –