2017-10-24 18 views
10

मैं AVCaptureAudioDataOutputSampleBufferDelegate में कैप्चरऑटपुट द्वारा लौटाए गए एक CMSampleBuffer की एक प्रति बनाने की कोशिश कर रहा हूं।ऑडियो CMSampleBuffer की गहरी प्रतिलिपि

मेरी समस्या यह है कि मेरे फ्रेम captureOutput:didOutputSampleBuffer:fromConnection: से आने वाले बाद में CFArray में उन्हें बनाए रखने के बाद गिराए जा रहे हैं।

जाहिर है, मुझे आगे की प्रक्रिया के लिए आने वाले बफर की गहरी प्रतियां बनाने की आवश्यकता है। मुझे यह भी पता है कि CMSampleBufferCreateCopy केवल उथले प्रतियां बनाता है।

इतने पर पूछा गया कुछ संबंधित प्रश्नों के होते हैं:

लेकिन उनमें से कोई भी 12 मानकों के साथ सही ढंग से CMSampleBufferCreate समारोह का उपयोग करने के लिए मुझे मदद करता है:

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); 
    } 

आप ऑडियो CMSampleBuffer की गहरी प्रतिलिपि कैसे बनाते हैं? अपने उत्तरों में किसी भी भाषा (स्विफ्ट/उद्देश्य-सी) का उपयोग करने के लिए स्वतंत्र महसूस करें।

+0

क्या यह स्पष्ट है कि आपको एक गहरी प्रतिलिपि की आवश्यकता है? जब आप 'CMSampleBufferCreateCopy' का उपयोग करते हैं तो क्या होता है? क्या 'CMSampleBufferCopySampleBufferForRange' आपको एक गहरी प्रतिलिपि देगा? क्या आपको वास्तव में आगे की प्रक्रिया के लिए 'सीएमएसएमएल बफर' की आवश्यकता है? यदि आप अपनी खुद की प्रसंस्करण कर रहे हैं, तो लंबाई + सूचक अधिक सुविधाजनक हो सकता है। –

+0

@ रिथमिक फ़िस्टमैन हां, यह स्पष्ट है कि मुझे गहरी प्रतिलिपि की आवश्यकता है, अगर मैं 'CMSampleBufferCreateCopy' का उपयोग करता हूं और फिर 1 से अधिक से अधिक 'CFArray' में कॉपी किए गए नमूना को बनाए रखता हूं,' didOutputSampleBuffer' कॉल हो रहा है। आप आसानी से इसे [प्रश्न] (https://stackoverflow.com/questions/30850676/avcaptureoutput-didoutputsamplebuffer-stops-getting-called) के साथ पुन: उत्पन्न कर सकते हैं। मैं 'CMSampleBufferCopySampleBufferForRange' के साथ व्यवहार की जांच करूंगा और आपको अपडेट कर दूंगा। –

+0

आह, ठीक है, बफर को बनाए रखने वाले बफर आपके प्रतिनिधि कॉलबैक महत्वपूर्ण जानकारी हैं। क्या आपके पास उपरोक्त कोड के एक चलने योग्य संस्करण का लिंक है? –

उत्तर

6

यहां एक कामकाजी समाधान है जिसे मैंने अंततः कार्यान्वित किया। मैंने इस स्निपेट को ऐप्पल डेवलपर तकनीकी समर्थन में भेजा और उनसे पूछा कि यह आने वाले नमूना बफर की प्रतिलिपि बनाने का सही तरीका है या नहीं। मूल विचार AudioBufferList कॉपी करें और फिर CMSampleBuffer बनाएं और इस नमूने में AudioBufferList सेट करें।

 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; 
     } 

कोड स्तरीय समर्थन जवाब:

इस कोड को ठीक लग रहा है (आपको कुछ अतिरिक्त त्रुटि जाँच जोड़ना चाहें, हालांकि)। मैंने इसे ऐप में सफलतापूर्वक परीक्षण किया है जो ऑडियो कैप्चर और रिकॉर्ड करने के लिए AVCaptureAudioDataOutput प्रतिनिधि captureOutput:didOutputSampleBuffer:fromConnection: विधि लागू करता है। इस गहरे प्रतिलिपि कोड का उपयोग करते समय मुझे प्राप्त कैप्चर किया गया ऑडियो वही होता है जो सीधे प्रदान किए गए नमूना बफर (गहरी प्रतिलिपि के बिना) का उपयोग करते समय मिलता है।

ऐप्पल डेवलपर तकनीकी सहायता

+0

यह बहुत अच्छा है, लेकिन मैं वीडियो नमूने के साथ एक समान समस्या में भाग रहा हूं (मुझे नमूना बफर बनाए रखने की आवश्यकता है)। क्या आपके पास इसके लिए इसे कार्यान्वित करने के बारे में कोई सुझाव है? –

संबंधित मुद्दे