参考
我已经通过 SO 中的可能很好的链接从图像的 NSArray 创建视频文件。最有用的一个是这个SO Question Links
问题
- 现在 VideoToolBox 中存在内存泄漏。(我在 iOS 5.1 模拟器中运行应用程序时附上了仪器的屏幕截图)
- 我的应用程序在创建此视频时使用了 346 MB 的内存。主要是因为这个方法。
(BOOL)appendPixelBuffer:(CVPixelBufferRef)pixelBuffer withPresentationTime:(CMTime)presentationTime
AVAssetWriterInputPixelBufferAdaptor 类的这个方法会保留所有的 CVPixelBufferRef 直到视频被创建。
代码
我创建了一个 ImageToVideo.m NSOperation 类来从图像创建视频。
#import "ImageToVideo.h"
@implementation ImageToVideo
//global pixcel buffer.
CVPixelBufferRef pxbuffer = NULL;
- (void) pixelBufferFromCGImage:(CGImageRef)image size:(CGSize)size
{
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
[NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
nil];
CVBufferRelease(pxbuffer);
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, size.width,
size.height, kCVPixelFormatType_32ARGB, (CFDictionaryRef) options,
&pxbuffer);
options = nil;
[options release];
status=status;//Added to make the stupid compiler not show a stupid warning.
NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);
CVPixelBufferLockBaseAddress(pxbuffer, 0);
void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
NSParameterAssert(pxdata != NULL);
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pxdata, size.width,
size.height, 8, 4*size.width, rgbColorSpace,
kCGImageAlphaNoneSkipFirst);
NSParameterAssert(context);
CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image),
CGImageGetHeight(image)), image);
CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
}
- (void)writeImageAsMovietoPath:(NSString*)path size:(CGSize)size
{
NSError *error = nil;
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] retain];
AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor
assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput
sourcePixelBufferAttributes:nil];
NSParameterAssert(writerInput);
NSParameterAssert([videoWriter canAddInput:writerInput]);
[videoWriter addInput:writerInput];
NSMutableArray *photoImages = [[[NSMutableArray alloc] init] autorelease];
//Creating a image Array
for (int i = 0; i = [photoImages count])
{
CVBufferRelease(pxbuffer);
pxbuffer = NULL;
}
else
{
//creating the pixcel buffer.
[self pixelBufferFromCGImage:[[photoImages objectAtIndex:i] CGImage] size:CGSizeMake(640, 980)];
}
if (pxbuffer)
{
// append buffer
[adaptor appendPixelBuffer:pxbuffer withPresentationTime:presentTime];
CVBufferRelease(pxbuffer);
pxbuffer = NULL;
i++;
}
else
{
//Finish the session:
[writerInput markAsFinished];
[videoWriter finishWriting];
CVPixelBufferPoolRelease(adaptor.pixelBufferPool);
[videoWriter release];
[writerInput release];
NSLog (@"Done");
break;
}
}
}
//release the photoImage array.
[photoImages removeAllObjects];
}
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
// Unable to save the image
if (error)
{
UIAlertView *alert;
alert = [[UIAlertView alloc] initWithTitle:@"Error"
message:@"Unable to save image to Photo Album."
delegate:self cancelButtonTitle:@"Ok"
otherButtonTitles:nil];
[alert show];
[alert release];
}
}
- (void) main
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Operation Started");
NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"Documents/movie.mp4"]];
CGSize size = CGSizeMake(640, 960);
[self writeImageAsMovietoPath:path size:size] ;
[pool drain];
}
@end
问题
- 为什么 VideoToolBox 中存在内存泄漏?
- 有没有更好的方法将图像列表转换为 iOS 中的视频?
- 创建视频时如何减少我的应用程序内存占用?