我正在开发一个电影制作应用程序,它可以对导入的视频产生一些影响。 我正在使用AVAssetWriter来编写我的应用程序代码。 一切都很好,但我的记忆力很大。 我的应用程序在缓冲过程中占用了超过500 MB的RAM。 制作过滤视频的算法就像这样:
1-导入视频。
2-提取视频的所有帧作为CMSampleBuffer对象。
3-将CMSampleBuffer对象转换为uiimage。
4-在uiimage上实现过滤器。
5-将uiimage转换回新的CMSAmpleBuffer对象。
6-将新缓冲区附加到写入器输出。
7-最后将新电影保存到PhotoGallery。
问题出在 step5 我有一个函数将UIImage转换为 cvpixelBuffer 对象并返回它。 然后我将CVPixelBuffer对象转换为CMSampleBuffer。 该函数增加了很多内存,应用程序最终崩溃。
这是我的代码:
-(CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image andSize:(CGSize)size
{
double height = CGImageGetHeight(image);
double width = CGImageGetWidth(image);
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
[NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
nil];
CVPixelBufferRef pxbuffer = NULL;
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, size.width,
size.height, kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef) options,
&pxbuffer);
if (status != kCVReturnSuccess) {
return NULL;
}
CVPixelBufferLockBaseAddress(pxbuffer, 0);
void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pxdata,size.width ,
size.height, 8, 4*size.width, rgbColorSpace,
kCGImageAlphaNoneSkipFirst);
CGFloat Y ;
if (height == size.height)
Y = 0;
else
Y = (size.height /2) - (height/2) ;
CGContextConcatCTM(context, CGAffineTransformMakeRotation(0));
CGContextDrawImage(context, CGRectMake(0, Y,width,height), image);
CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
return pxbuffer;
}
CGContextDrawImage 每帧转换内存增加2~5 MB。
我尝试了以下解决方案:
1-使用 CFRelease 释放pxbuffer。
2-我使用 CGImageRelease 来发布图片参考。
3-我用 @autoreleasepool 块包围了代码。
4-我使用 CGContextRelease 。
5- UIGraphicsEndImageContext 。
6-在Xcode中也使用了Analyze并修复了所有点。
以下是视频过滤的完整代码:
- (void)assetFilteringMethod:(FilterType)filterType AndAssetURL:(NSURL *)assetURL{
CMSampleBufferRef sbuff ;
[areader addOutput:rout];
[areader startReading];
UIImage* bufferedImage;
while ([areader status] != AVAssetReaderStatusCompleted) {
sbuff = [rout copyNextSampleBuffer];
if (sbuff == nil)
[areader cancelReading];
else{
if (writerInput.readyForMoreMediaData) {
@autoreleasepool {
bufferedImage = [self imageFromSampleBuffer:sbuff];
bufferedImage = [FrameFilterClass convertImageToFilterWithFilterType:filterType andImage: bufferedImage];
CVPixelBufferRef buffer = NULL;
buffer = [self pixelBufferFromCGImage:[bufferedImage CGImage] andSize:CGSizeMake(320,240)];
[adaptor appendPixelBuffer:buffer withPresentationTime:CMSampleBufferGetPresentationTimeStamp(sbuff)];
CFRelease(buffer);
CFRelease(sbuff);
}
}
}
}
//Finished buffering
[videoWriter finishWritingWithCompletionHandler:^{
if (videoWriter.status != AVAssetWriterStatusFailed && videoWriter.status == AVAssetWriterStatusCompleted){
dispatch_async(dispatch_get_main_queue(), ^{
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if ([library
videoAtPathIsCompatibleWithSavedPhotosAlbum:[NSURL fileURLWithPath:moviePath]]) {
[library writeVideoAtPathToSavedPhotosAlbum:[NSURL fileURLWithPath:moviePath]
completionBlock:^(NSURL *assetURL, NSError *error){
}];
}
});
}
else
NSLog(@"Video writing failed: %@", videoWriter.error);
}];
}
我花了大约3到4天试图解决这个问题...... 任何帮助,将不胜感激。
答案 0 :(得分:0)
您必须使用以下行释放图像:
cgimagerelease(image.cgimage)