나는 가져온 비디오에 영향을주는 영화 제작자 응용 프로그램을 개발 중입니다. AVAssetWriter를 사용하여 응용 프로그램을 코딩하고 있습니다. 모든 것이 잘 작동하지만 메모리에 큰 문제가 있습니다. 내 앱이 버퍼링 과정에서 500MB 이상의 RAM을 차지합니다. 필터링 된 비디오를 만들기위한 알고리즘은 다음과 같습니다.CGContextDrawImage 거대한 메모리 피크
1- 가져 오기 비디오.
2 비디오의 모든 프레임을 CMSampleBuffer 개체로 추출합니다.
3 CMSampleBuffer 객체를 uiimage로 변환하십시오.
4 - uiimage에 필터를 구현하십시오.
5 uiimage를 새 CMSAmpleBuffer 객체로 다시 변환합니다.
6 작성자 출력에 새 버퍼를 추가합니다.
7- 마지막으로 새 동영상을 PhotoGallery에 저장합니다.
문제는 5 단계에 내가 cvpixelBuffer 객체에있는 UIImage을 변환하고 그것을 돌려 기능을 가지고있다. 그런 다음 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메가바이트하여 메모리를 증가 :
이 내 코드입니다. CFRelease를 사용 pxbuffer 해제
1 :
나는 다음과 같은 솔루션을 시도했다.2 나는 CGImageRelease을 사용하여 이미지를 공개합니다.
3 - 나는 코드를 @autoreleasepool 블록으로 둘러 쌌다.
4- 나는 CGContextRelease을 사용했습니다.
5- UIGraphicsEndImageContext.
6 사용 Xcode에서 분석하여 모든 점을 고정했습니다.
여기에 비디오 필터링에 대한 전체 코드입니다 :
- (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 일 동안은 ... 어떤 도움을 주시면 감사하겠습니다.
은 WOW가, Thankssssss 일! – user3125119