2013-02-13 48 views
18

मेरे पास AVAssetWriterInput appendSampleBuffer के साथ एक अजीब स्मृति "रिसाव" है। मैं एक ही समय में वीडियो और ऑडियो लिख रहा हूँ, इसलिए मैं दो आदानों, वीडियो के लिए और एक ऑडियो के लिए के साथ एक AVAssetWriter है:एक ऑडियो AVAssetWriterInput "leaks" स्मृति के साथ appendSampleBuffer endSessionAtSourceTime

self.videoWriter = [[[AVAssetWriter alloc] initWithURL:[self.currentVideo currentVideoClipLocalURL] 
               fileType:AVFileTypeMPEG4 
               error:&error] autorelease]; 
... 
self.videoWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo 
                  outputSettings:videoSettings]; 
self.videoWriterInput.expectsMediaDataInRealTime = YES; 
[self.videoWriter addInput:self.videoWriterInput]; 
... 
self.audioWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio 
                  outputSettings:audioSettings]; 
self.audioWriterInput.expectsMediaDataInRealTime = YES; 
[self.videoWriter addInput:self.audioWriterInput]; 

मैं लिखना प्रारंभ करें और सब कुछ सतह पर ठीक काम करता है। वीडियो और ऑडियो लिखा मिलता है और गठबंधन कर रहे हैं, आदि हालांकि, मैं आवंटन साधन के माध्यम से अपने कोड डाल दिया और निम्नलिखित देखा:

CoreMedia allocations

ऑडियो बाइट्स स्मृति में बनाए रखा जा रहा है, जैसा कि मैंने साबित कर देंगे क्षण भर में। यह स्मृति में रैंप अप है। ऑडियो बाइट्स केवल [self.videoWriter endSessionAtSourceTime:...] पर कॉल करने के बाद ही जारी किए जाते हैं, जिन्हें आप स्मृति उपयोग में नाटकीय ड्रॉप के रूप में देखते हैं।

@autoreleasepool 
{ 
    // The objects that will hold the audio data 
    CMSampleBufferRef sampleBuffer; 
    CMBlockBufferRef blockBuffer1; 
    CMBlockBufferRef blockBuffer2; 

    size_t nbytes = numSamples * asbd_.mBytesPerPacket; 

    OSStatus status = noErr; 
    status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault, 
               data, 
               nbytes, 
               kCFAllocatorNull, 
               NULL, 
               0, 
               nbytes, 
               kCMBlockBufferAssureMemoryNowFlag, 
               &blockBuffer1); 

    if (status != noErr) 
    { 
     NLog(@"CMBlockBufferCreateWithMemoryBlock error at buffer 1"); 
     return; 
    } 

    status = CMBlockBufferCreateContiguous(kCFAllocatorDefault, 
              blockBuffer1, 
              kCFAllocatorDefault, 
              NULL, 
              0, 
              nbytes, 
              kCMBlockBufferAssureMemoryNowFlag | kCMBlockBufferAlwaysCopyDataFlag, 
              &blockBuffer2); 

    if (status != noErr) 
    { 
     NSLog(@"CMBlockBufferCreateWithMemoryBlock error at buffer 2"); 
     CFRelease(blockBuffer1); 
     return; 
    } 

    // Finally, create the CMSampleBufferRef 
    status = CMAudioSampleBufferCreateWithPacketDescriptions(kCFAllocatorDefault, 
                  blockBuffer2, 
                  YES, // Yes data is ready 
                  NULL, // No callback needed to make data ready 
                  NULL, 
                  audioFormatDescription_, 
                  1, 
                  timestamp, 
                  NULL, 
                  &sampleBuffer); 


    if (status != noErr) 
    { 
     NSLog(@"CMAudioSampleBufferCreateWithPacketDescriptions error."); 
     CFRelease(blockBuffer1); 
     CFRelease(blockBuffer2); 
     return; 
    } 

    if ([self.audioWriterInput isReadyForMoreMediaData]) 
    { 
     if (![self.audioWriterInput appendSampleBuffer:sampleBuffer]) 
     { 
      NSLog(@"Couldn't append audio sample buffer: %d", numAudioCallbacks_); 
     } 
    } else { 
     NSLog(@"AudioWriterInput isn't ready for more data."); 
    } 

    // One release per create 
    CFRelease(blockBuffer1); 
    CFRelease(blockBuffer2); 
    CFRelease(sampleBuffer); 
} 

आप देख सकते हैं, मैं एक बफर एक बार बनाने के प्रति जारी कर रहा हूँ: यहाँ मेरे ऑडियो लेखन कोड है, जो एक सीरियल कतार पर एक ब्लॉक के रूप में भेजा जाता है। मैं "रिसाव" का पता लगाया गया है लाइन जहां ऑडियो बफर जोड़ दिए जाते हैं करने के लिए नीचे:

[self.audioWriterInput appendSampleBuffer:sampleBuffer] 

मुझे लगता है कि लाइन है, जिसके बाद मैं निम्नलिखित "रिसाव से मुक्त" आवंटन ग्राफ मिल बाहर टिप्पणी करके अपने आप को यह साबित कर दिया (हालांकि रिकॉर्ड किए गए वीडियो अब अब कोई ऑडियो, निश्चित रूप से है):

:

No leak

मैं एक दूसरी बात, appendSamplebuffer लाइन और इसके बजाय डबल रिहाई blockBuffer2 वापस जोड़ने के लिए है जो करने की कोशिश की

ऐसा किया कर नहीं कारण एक डबल मुक्त, यह दर्शाता है कि blockBuffer2 के उस बिंदु पर गिनती बनाए रखने 2. यह वही "रिसाव से मुक्त" आवंटन ग्राफ, अपवाद के साथ उत्पादन किया है जब मैं कहा जाता है कि [self.videoWriter endSessionAtSourceTime:...], मुझे डबल-रिलीज से एक क्रैश मिलता है (यह दर्शाता है कि self.videoWriter अपने सभी पॉइंटर्स को blockBuffer2 एस में पारित करने की कोशिश कर रहा है)।

अगर इसके बजाय, मैं निम्न प्रयास करें:

CFRelease(blockBuffer1); 
CFRelease(blockBuffer2); 
CMSampleBufferInvalidate(sampleBuffer); // Invalidate sample buffer 
CFRelease(sampleBuffer); 

तो [self.audioWriterInput appendSampleBuffer:sampleBuffer]और कॉल संलग्न करने के लिए वीडियो फ्रेम उसके बाद हर कॉल के लिए असफल करने के लिए शुरू।

तो मेरा निष्कर्ष यह है कि AVAssetWriter या AVAssetWriterInput वीडियो रिकॉर्डिंग समाप्त होने तक blockBuffer2 बनाए रख रहा है। जाहिर है, अगर वीडियो लंबे समय तक रिकॉर्डिंग कर रहा है तो यह वास्तविक स्मृति समस्याओं का कारण बन सकता है। क्या मुझसे कुछ गलत हो रही है?

संपादित करें: मुझे प्राप्त होने वाले ऑडियो बाइट्स पीसीएम प्रारूप हैं, जबकि मैं जिस वीडियो प्रारूप को लिख रहा हूं वह एमपीईजी 4 है और उस वीडियो के लिए ऑडियो प्रारूप एमपीईजी 4 एएसी है। क्या यह संभव है कि वीडियो लेखक फ्लाई पर पीसीएम -> एएसी प्रारूप कर रहा है, और यही कारण है कि यह buffered हो रहा है?

+0

मुझे यकीन है कि आपने चारों ओर देखा है लेकिन आपने इन दो प्रश्नों/उत्तरों को देखा है। वे सहायक/संबंधित हो सकते हैं। 1) http://stackoverflow.com/questions/4914853/help-fix-memory-leak-release 2) http://stackoverflow.com/questions/11274652/performance-issues-when-using-avcapturevideodataoutput-and-avcaptureaudiodataout – JSuar

+0

@JSuar के सुझावों के लिए धन्यवाद। मैंने पहले से ही पहले की कोशिश की है, लेकिन CMSampleBufferInvalidate को कॉल करने से सभी लेखक वीडियो लेखक को लिखते हैं। दूसरा दिलचस्प दिखता है, लेकिन मुझे यकीन नहीं है कि समवर्ती या सीरियल कतार स्मृति "रिसाव" की व्याख्या करेगी, जो ऑडियो ब्लॉक को बनाए रखने वाले वीडियो लेखन के कारण होती है। – kevlar

+0

क्या यह संभव है कि आप वीडियो को वीडियो से बहुत तेज लिख रहे हों, इसलिए इसे इंटरलीव को सही रखने के लिए buffered की आवश्यकता है? –

उत्तर

1

चूंकि आप एक उत्तर के लिए एक महीने का इंतजार कर रहे हैं, इसलिए मैं आपको आदर्श लेकिन व्यावहारिक उत्तर से कम दूंगा।

आप एक अलग फ़ाइल लिखने के लिए विस्तारितऑडियो फाइल फ़ंक्शंस का उपयोग कर सकते हैं। फिर आप एक AVComposition के साथ वीडियो और ऑडियो प्लेबैक कर सकते हैं। मुझे लगता है कि यदि आप रिकॉर्डिंग के अंत में उन्हें मिश्रित करने की आवश्यकता है तो आप फिर से कंसोडिंग के बिना कैफ और वीडियो को मिश्रित करने के लिए AVFoundation का उपयोग करने में सक्षम हो सकते हैं।

जो आपको बंद कर देगा और दौड़ देगा, तो आप अपने अवकाश पर मेमोरी रिसाव को हल कर सकते हैं।

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

  • कोई संबंधित समस्या नहीं^_^