現在、いくつかのコードをデバッグしています。ムービー ファイルをフレーム配列に読み込み、フレームにいくつかの変換を適用し、すべてをコンパイルしてビデオ ファイルに戻します。自分で呼び出したすべてのメモリ リークを修正しましたが、残りの 1 つはかなり深刻です。プロセス後、約 400 MB のメモリが残ります。これがリークのスクリーンショットです。
ご覧のとおり、より高いレベルの呼び出しは VideoToolbox ライブラリにのみあります。しかし、私はこのライブラリをプロジェクトに含めていません。このリークが Apple のライブラリに付属しているとは思えず、私にできることは何もありません。
これは、コール ツリーで言及された h264 とデコードに関連するものを使用する唯一のコードです。
-(void)writeImageAsMovie:(NSArray *)array toPath:(NSString*)path size:(CGSize)size
{
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
}
NSError *error = nil;
// FIRST, start up an AVAssetWriter instance to write your video
// Give it a destination path (for us: tmp/temp.mov)
AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:path]
fileType:AVFileTypeQuickTimeMovie
error:&error];
NSParameterAssert(videoWriter);
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecH264, AVVideoCodecKey,
[NSNumber numberWithInt:size.width], AVVideoWidthKey,
[NSNumber numberWithInt:size.height], AVVideoHeightKey,
nil];
AVAssetWriterInput* writerInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
outputSettings:videoSettings];
AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput
sourcePixelBufferAttributes:nil];
NSParameterAssert(writerInput);
NSParameterAssert([videoWriter canAddInput:writerInput]);
[videoWriter addInput:writerInput];
//Start a SESSION of writing.
// After you start a session, you will keep adding image frames
// until you are complete - then you will tell it you are done.
[videoWriter startWriting];
// This starts your video at time = 0
[videoWriter startSessionAtSourceTime:kCMTimeZero];
CVPixelBufferRef buffer = NULL;
//int frameDuration = (1/fps)*600.0;
//NSLog(@"FRAME DURATION: %d",frameDuration);
int i = 0;
while (1)
{
// Check if the writer is ready for more data, if not, just wait
if(writerInput.readyForMoreMediaData){
CMTime frameTime = CMTimeMake(1, fps);
// CMTime = Value and Timescale.
// Timescale = the number of tics per second you want
// Value is the number of tics
// For us - each frame we add will be 1/4th of a second
// Apple recommend 600 tics per second for video because it is a
// multiple of the standard video rates 24, 30, 60 fps etc.
CMTime lastTime=CMTimeMake(i, fps);
CMTime presentTime=CMTimeAdd(lastTime, frameTime);
if (i == 0) {presentTime = CMTimeMake(0, 600);}
// This ensures the first frame starts at 0.
if (i >= [array count])
{
buffer = NULL;
}
else
{
// This command grabs the next UIImage and converts it to a CGImage
CVPixelBufferRef tempBuffer = buffer;
CVPixelBufferRelease(tempBuffer);
buffer = [self pixelBufferFromCGImage:[[array objectAtIndex:i] CGImage]andSize:size];
}
if (buffer)
{
// Give the CGImage to the AVAssetWriter to add to your video
[adaptor appendPixelBuffer:buffer withPresentationTime:presentTime];
i++;
}
else
{
//Finish the session:
// This is important to be done exactly in this order
[writerInput markAsFinished];
// WARNING: finishWriting in the solution above is deprecated.
// You now need to give a completion handler.
[videoWriter finishWritingWithCompletionHandler:^{
NSLog(@"Finished writing...checking completion status...");
if (videoWriter.status != AVAssetWriterStatusFailed && videoWriter.status == AVAssetWriterStatusCompleted)
{
NSLog(@"Video writing succeeded.");
// Move video to camera roll
// NOTE: You cannot write directly to the camera roll.
// You must first write to an iOS director then move it!
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *audioTemp = [documentsDirectory stringByAppendingPathComponent:@"/temp-audio.m4a"];
NSString *finalTemp = [documentsDirectory stringByAppendingPathComponent:@"/temp.mov"];
[self mergeVideoFromPath:[NSURL fileURLWithPath:path] withAudioFromPath:[NSURL fileURLWithPath:audioTemp] atPath:[NSURL fileURLWithPath:finalTemp]];
} else
{
NSLog(@"Video writing failed: %@", videoWriter.error);
}
}]; // end videoWriter finishWriting Block
CVPixelBufferRelease(buffer);
CVPixelBufferPoolRelease(adaptor.pixelBufferPool);
NSLog (@"Done");
break;
}
}
}
}