मेरे पास 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];
मैं लिखना प्रारंभ करें और सब कुछ सतह पर ठीक काम करता है। वीडियो और ऑडियो लिखा मिलता है और गठबंधन कर रहे हैं, आदि हालांकि, मैं आवंटन साधन के माध्यम से अपने कोड डाल दिया और निम्नलिखित देखा:
ऑडियो बाइट्स स्मृति में बनाए रखा जा रहा है, जैसा कि मैंने साबित कर देंगे क्षण भर में। यह स्मृति में रैंप अप है। ऑडियो बाइट्स केवल [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]
मुझे लगता है कि लाइन है, जिसके बाद मैं निम्नलिखित "रिसाव से मुक्त" आवंटन ग्राफ मिल बाहर टिप्पणी करके अपने आप को यह साबित कर दिया (हालांकि रिकॉर्ड किए गए वीडियो अब अब कोई ऑडियो, निश्चित रूप से है):
:मैं एक दूसरी बात, 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 हो रहा है?
मुझे यकीन है कि आपने चारों ओर देखा है लेकिन आपने इन दो प्रश्नों/उत्तरों को देखा है। वे सहायक/संबंधित हो सकते हैं। 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
@JSuar के सुझावों के लिए धन्यवाद। मैंने पहले से ही पहले की कोशिश की है, लेकिन CMSampleBufferInvalidate को कॉल करने से सभी लेखक वीडियो लेखक को लिखते हैं। दूसरा दिलचस्प दिखता है, लेकिन मुझे यकीन नहीं है कि समवर्ती या सीरियल कतार स्मृति "रिसाव" की व्याख्या करेगी, जो ऑडियो ब्लॉक को बनाए रखने वाले वीडियो लेखन के कारण होती है। – kevlar
क्या यह संभव है कि आप वीडियो को वीडियो से बहुत तेज लिख रहे हों, इसलिए इसे इंटरलीव को सही रखने के लिए buffered की आवश्यकता है? –