2016-06-17 9 views
1

Я разрабатываю приложение для создания фильмов, которое влияет на импортированные видео. Я использую AVAssetWriter для кодирования своего приложения. Все работает очень хорошо, но у меня большая проблема в памяти. Мое приложение занимает более 500 МБ оперативной памяти в процессе буферизации. Просто алгоритм для создания отфильтрованного видео выглядит следующим образом:CGContextDrawImage огромный пик памяти

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 МБ на преобразование кадров.

Я попытался следующие решения:

1- рилизинг pxbuffer использованием CFRelease.

2- Я использовал CGImageRelease, чтобы снять изображение ref.

3- Я окружил код @autoreleasepool блок.

4- Я использовал CGContextRelease.

5- UIGraphicsEndImageContext.

6- Использовал Analyse тоже в 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

Смежные вопросы