iOS開発とstackoverflowの両方に新しいので、私のコードが見栄えが良くない場合は私にご負担ください。
ARCとAVAssetWriter
を使ってテストアプリケーションをセットアップして、アプリケーションバンドルに存在する画像を含むビデオを作成しました。すべてが期待どおりに動作し、ビデオが正しく作成されますが、Instrumentsでアプリケーションのプロファイルを作成すると、私のコードに関連する詳細ビューでは何も表示されないため、修正方法がわからないメモリリークが発生します(すべての流出オブジェクトはMallocであり、責任ライブラリはVideoToolbox
です)。ここ
は、私は私のビューコントローラクラスでビデオの書き込みを開始するために呼び出すメソッドです:
iOS AVAssetWriterを使用して画像からビデオを作成するとメモリリークが発生する
- (void)writeVideo
{
// Set the frameDuration ivar (50/600 = 1 sec/12 number of frames)
frameDuration = CMTimeMake(50, 600);
nextPresentationTimeStamp = kCMTimeZero;
[self deleteTempVideo];
NSError *error = nil;
AVAssetWriter *writer = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:self.videoPath] fileType:AVFileTypeQuickTimeMovie error:&error];
if (!error) {
// Define video settings to be passed to the AVAssetWriterInput instance
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecH264, AVVideoCodecKey,
[NSNumber numberWithInt:640],AVVideoWidthKey,
[NSNumber numberWithInt:480], AVVideoHeightKey, nil];
// Instanciate the AVAssetWriterInput
AVAssetWriterInput *writerInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings];
// Instanciate the AVAssetWriterInputPixelBufferAdaptor to be connected to the writer input
AVAssetWriterInputPixelBufferAdaptor *pixelBufferAdaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput sourcePixelBufferAttributes:nil];
// Add the writer input to the writer and begin writing
[writer addInput:writerInput];
[writer startWriting];
[writer startSessionAtSourceTime:nextPresentationTimeStamp];
//
dispatch_queue_t mediaDataRequestQueue = dispatch_queue_create("Media data request queue", NULL);
[writerInput requestMediaDataWhenReadyOnQueue:mediaDataRequestQueue usingBlock:^{
while (writerInput.isReadyForMoreMediaData) {
CVPixelBufferRef nextBuffer = [self fetchNextPixelBuffer];
if (nextBuffer) {
[pixelBufferAdaptor appendPixelBuffer:nextBuffer withPresentationTime:nextPresentationTimeStamp];
nextPresentationTimeStamp = CMTimeAdd(nextPresentationTimeStamp, frameDuration);
CVPixelBufferRelease(nextBuffer);
dispatch_async(dispatch_get_main_queue(), ^{
NSUInteger totalFrames = [self.imagesNames count];
float progress = 1.0 * (totalFrames - [self.imageNamesCopy count])/totalFrames;
[self.progressBar setProgress:progress animated:YES];
});
} else {
[writerInput markAsFinished];
[writer finishWriting];
[self loadVideo];
dispatch_release(mediaDataRequestQueue);
break;
}
}
}];
}
}
そして、ここでは、私はインスタンス化ピクセルバッファアダプタに追加するピクセルバッファをフェッチするために使用する方法であり、従来の方法では:
// Consume the imageNamesCopy mutable array and return a CVPixelBufferRef relative to the last object of the array
- (CVPixelBufferRef)fetchNextPixelBuffer
{
NSString *imageName = [self.imageNamesCopy lastObject];
if (imageName) [self.imageNamesCopy removeLastObject];
// Create an UIImage instance
UIImage *image = [UIImage imageNamed:imageName];
CGImageRef imageRef = image.CGImage;
CVPixelBufferRef buffer = NULL;
size_t width = CGImageGetWidth(imageRef);
size_t height = CGImageGetHeight(imageRef);
// Pixel buffer options
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
[NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, nil];
// Create the pixel buffer
CVReturn result = CVPixelBufferCreate(NULL, width, height, kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef) options, &buffer);
if (result == kCVReturnSuccess && buffer) {
CVPixelBufferLockBaseAddress(buffer, 0);
void *bufferPointer = CVPixelBufferGetBaseAddress(buffer);
// Define the color space
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// Create the bitmap context to draw the image
CGContextRef context = CGBitmapContextCreate(bufferPointer, width, height, 8, 4 * width, colorSpace, kCGImageAlphaNoneSkipFirst);
CGColorSpaceRelease(colorSpace);
if (context) {
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGContextRelease(context);
}
CVPixelBufferUnlockBaseAddress(buffer, 0);
}
return buffer;
}
AVAssetWriter * writerは決して解放されません。 – Allyn
@Allyn:多分私は何かが不足しているかもしれませんが、私はARCを使っているので、どうやってAVAssetWriter *ライターをリリースするのですか? – marco
申し訳ありませんが、ARCを使用しています。その場合、CVReturnの結果を決して公開しないかもしれない - 私はそれがARCによって処理されるとは思わない。 – Allyn