質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Objective-C

Objective-Cはオブジェクト指向型のプログラミング言語のひとつです。C言語をベースにSmalltalkが取り入れられています。

Q&A

2回答

2847閲覧

メモリリークの原因を教えてください

gotchcuru

総合スコア29

Objective-C

Objective-Cはオブジェクト指向型のプログラミング言語のひとつです。C言語をベースにSmalltalkが取り入れられています。

0グッド

1クリップ

投稿2016/06/15 06:16

編集2022/01/12 10:55

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 }

イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fuzzball

2016/06/15 06:23

質問のコードはObjective-Cに見えるのですが、Swiftに書き換えているのならそのコードを書いて下さい。Objective-Cで間違いないのであればタグを修正して下さい。
gotchcuru

2016/06/15 06:35

失礼しました!タグを修正しました
guest

回答2

0

Xcodeにはクソ便利なInstrumentsという機能が備わっています。これを使えば簡単なメモリリークは一発で見つかります。ここを参考にどうぞ。
http://pebble8888.hatenablog.com/entry/2013/08/21/232201

投稿2016/06/15 08:08

masaya_ohashi

総合スコア9206

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ググっただけで未検証ですが、CVBufferReleaseCVPixelBufferReleaseでどうでしょうか?

投稿2016/06/15 06:26

fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gotchcuru

2016/06/15 07:41

試してみましたがうまくいきませんでした。
gotchcuru

2016/06/15 07:58

メモリに関しては地検が浅く申し訳ないのですが、@autoreleasepoolなどで解決する手段はありませんでしょうか?
fuzzball

2016/06/15 08:03

そう思うなら試してみればいいのでは?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問