2016-06-17 3 views
1

나는 가져온 비디오에 영향을주는 영화 제작자 응용 프로그램을 개발 중입니다. 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 일 동안은 ... 어떤 도움을 주시면 감사하겠습니다.

답변

0

당신이 줄을 사용하여 이미지를 해제해야합니다 :

cgimagerelease(image.cgimage) 
+0

은 WOW가, Thankssssss 일! – user3125119

관련 문제