http://www.mdn.co.jp/di/book/3214303003/?page=2
上の本に書かれていたtipsをもとに、以下のようにコードを記述したのですが、
メモリリークが発生してしまい、原因と修正方法がわからないのでお教え頂きたいです。
コードの内容としては複数枚の静止画をつなぎ合わせ動画ファイルに変換しています。
漠然とした質問でも申し訳ありませんが、何卒よろしくおねがいします。。。
swift
1#import "MovieCreator.h" 2 3@implementation MovieCreator 4 5/*! 6 画像の配列から動画を生成する。 7 8 @param images 画像の配列 9 @param path 動画ファイルの出力先 10 */ 11- (void)writeImagesAsMovie:(NSArray *)images toPath:(NSString *)path 12{ 13 NSFileManager *fileManager = [NSFileManager defaultManager]; 14 15 // ファイルを削除する 16 [fileManager removeItemAtPath:path error:nil]; 17 18 // 最初の画像から動画のサイズ指定する 19 CGSize size = ((UIImage *)images[0]).size; 20 21 _videoWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:path] 22 fileType:AVFileTypeQuickTimeMovie 23 error:nil]; 24 25 NSDictionary *outputSettings = 26 @{ 27 AVVideoCodecKey : AVVideoCodecH264, 28 AVVideoWidthKey : @(size.width), 29 AVVideoHeightKey : @(size.height), 30 }; 31 32 AVAssetWriterInput *writerInput = [AVAssetWriterInput 33 assetWriterInputWithMediaType:AVMediaTypeVideo 34 outputSettings:outputSettings]; 35 36 [_videoWriter addInput:writerInput]; 37 38 AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor 39 assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput 40 sourcePixelBufferAttributes:nil]; 41 42 [_videoWriter startWriting]; 43 44 [_videoWriter startSessionAtSourceTime:kCMTimeZero]; 45 46 CVPixelBufferRef buffer = NULL; 47 48 int frameCount = 0; 49 // 次の画像を表示する時間感覚の設定です。 50 // この数字を小さくすると、早く画像が変わるので滑らかに動きます。 51 // この数字を大きくすると、かくかくした動画になり、面白いです。 52 float durationForEachImage = 0.5; 53 int32_t fps = 24; 54 55 for (UIImage *image in images) 56 { 57 if (adaptor.assetWriterInput.readyForMoreMediaData) 58 { 59 CMTime frameTime = CMTimeMake((int64_t)frameCount * fps * durationForEachImage, fps); 60 61 buffer = [self pixelBufferFromCGImage:image.CGImage]; 62 63 if (![adaptor appendPixelBuffer:buffer withPresentationTime:frameTime]) 64 { 65 NSLog(@"Failed to append buffer. [image : %@]", image); 66 } 67 68 if(buffer) { 69 CVBufferRelease(buffer); 70 } 71 72 frameCount++; 73 74 [NSThread sleepForTimeInterval:0.05]; 75 } 76 else 77 { 78 [NSThread sleepForTimeInterval:0.1]; 79 } 80 } 81 82 // 動画生成終了 83 [writerInput markAsFinished]; 84 [_videoWriter finishWritingWithCompletionHandler:^ 85 { 86 NSLog(@"Finish writing!"); 87 88 // 動画をカメラロールに保存する 89 UISaveVideoAtPathToSavedPhotosAlbum(path, self, nil, nil); 90 91 }]; 92 CVPixelBufferPoolRelease(adaptor.pixelBufferPool); 93} 94 95- (CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image 96{ 97 CVPixelBufferRef pxbuffer = NULL; 98 99 CVPixelBufferCreate(kCFAllocatorDefault, 100 CGImageGetWidth(image), 101 CGImageGetHeight(image), 102 kCVPixelFormatType_32ARGB, 103 NULL, 104 &pxbuffer); 105 106 CVPixelBufferLockBaseAddress(pxbuffer, 0); 107 void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer); 108 109 CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); 110 111 CGContextRef context = CGBitmapContextCreate(pxdata, 112 CGImageGetWidth(image), 113 CGImageGetHeight(image), 114 8, 115 4 * CGImageGetWidth(image), 116 colorspace, 117 (CGBitmapInfo)kCGImageAlphaNoneSkipFirst); 118 119 CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image); 120 121 CVPixelBufferUnlockBaseAddress(pxbuffer, 0); 122 123 CGContextRelease(context); 124 CGColorSpaceRelease(colorspace); 125 126 return pxbuffer; 127} 128@end
メモリの増加を追ってみると、以下の箇所でメモリが急上昇しております。
Swift
1int frameCount = 0; 2 // 次の画像を表示する時間感覚の設定です。 3 // この数字を小さくすると、早く画像が変わるので滑らかに動きます。 4 // この数字を大きくすると、かくかくした動画になり、面白いです。 5 float durationForEachImage = 0.5; 6 int32_t fps = 24; 7 8 for (UIImage *image in images) 9 { 10 if (adaptor.assetWriterInput.readyForMoreMediaData) 11 { 12 CMTime frameTime = CMTimeMake((int64_t)frameCount * fps * durationForEachImage, fps); 13 14 buffer = [self pixelBufferFromCGImage:image.CGImage]; 15 16 if (![adaptor appendPixelBuffer:buffer withPresentationTime:frameTime]) 17 { 18 NSLog(@"Failed to append buffer. [image : %@]", image); 19 } 20 21 if(buffer) { 22 CVBufferRelease(buffer); 23 } 24 25 frameCount++; 26 27 [NSThread sleepForTimeInterval:0.05]; 28 } 29 else 30 { 31 [NSThread sleepForTimeInterval:0.1]; 32 } 33 }