6

비디오 캡처 및 처리를 위해 CGImage로 변환 중입니다. ~ 10 초 동안 작동하고 메모리 경고를받은 다음 충돌합니다 (대개 데이터 포맷터를 일시적으로 사용할 수 없다고 말함). 누군가 내가 문제를 해결하도록 도울 수 있습니까? 이미지를 변환하는iPhone : AVCaptureSession 캡처 출력 충돌 (AVCaptureVideoDataOutput)

- (void) captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { 

// CONVERT CMSAMPLEBUFFER INTO A CGIMAGE 
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 

CVPixelBufferLockBaseAddress(imageBuffer,0); 


uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer); 
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
size_t width = CVPixelBufferGetWidth(imageBuffer); 
size_t height = CVPixelBufferGetHeight(imageBuffer); 


CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 
CGImageRef cgimage = CGBitmapContextCreateImage(newContext); 
UIImage *sourceImage= [UIImage imageWithCGImage:cgimage scale:1.0f orientation:UIImageOrientationLeftMirrored]; 
CGImageRelease(cgimage); 
CGContextRelease(newContext); 
CGColorSpaceRelease(colorSpace); 

CVPixelBufferUnlockBaseAddress(imageBuffer,0); 


// *** 
// Adding code after this point to do image transformation usually causes it to crash 
UIImage *rot = [self scaleAndRotateImage:sourceImage]; 
self.detectImage = rot; 



} 

코드 ....

- (UIImage*)scaleAndRotateImage:(UIImage *)image{ 
    int kMaxResolution = 320; // Or whatever 

    CGImageRef imgRef = image.CGImage; 

    CGFloat width = CGImageGetWidth(imgRef); 
    CGFloat height = CGImageGetHeight(imgRef); 

    CGAffineTransform transform = CGAffineTransformIdentity; 
    CGRect bounds = CGRectMake(0, 0, width, height); 
    if (width > kMaxResolution || height > kMaxResolution) { 
     CGFloat ratio = width/height; 
     if (ratio > 1) { 
      bounds.size.width = kMaxResolution; 
      bounds.size.height = bounds.size.width/ratio; 
     } 
     else { 
      bounds.size.height = kMaxResolution; 
      bounds.size.width = bounds.size.height * ratio; 
     } 
    } 

    CGFloat scaleRatio = bounds.size.width/width; 
    CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef)); 
    CGFloat boundHeight; 
    UIImageOrientation orient = image.imageOrientation; 
    switch(orient) { 

     case UIImageOrientationUp: //EXIF = 1 
      transform = CGAffineTransformIdentity; 
      break; 

     case UIImageOrientationUpMirrored: //EXIF = 2 
      transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0); 
      transform = CGAffineTransformScale(transform, -1.0, 1.0); 
      break; 

     case UIImageOrientationDown: //EXIF = 3 
      transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height); 
      transform = CGAffineTransformRotate(transform, M_PI); 
      break; 

     case UIImageOrientationDownMirrored: //EXIF = 4 
      transform = CGAffineTransformMakeTranslation(0.0, imageSize.height); 
      transform = CGAffineTransformScale(transform, 1.0, -1.0); 
      break; 

     case UIImageOrientationLeftMirrored: //EXIF = 5 
      boundHeight = bounds.size.height; 
      bounds.size.height = bounds.size.width; 
      bounds.size.width = boundHeight; 
      transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.height); 
      transform = CGAffineTransformScale(transform, -1.0, 1.0); 
      transform = CGAffineTransformRotate(transform, 3.0 * M_PI/2.0); 
      break; 

     case UIImageOrientationLeft: //EXIF = 6 
      boundHeight = bounds.size.height; 
      bounds.size.height = bounds.size.width; 
      bounds.size.width = boundHeight; 
      transform = CGAffineTransformMakeTranslation(0.0, imageSize.width); 
      transform = CGAffineTransformRotate(transform, 3.0 * M_PI/2.0); 
      break; 

     case UIImageOrientationRightMirrored: //EXIF = 7 
      boundHeight = bounds.size.height; 
      bounds.size.height = bounds.size.width; 
      bounds.size.width = boundHeight; 
      transform = CGAffineTransformMakeScale(-1.0, 1.0); 
      transform = CGAffineTransformRotate(transform, M_PI/2.0); 
      break; 

     case UIImageOrientationRight: //EXIF = 8 
      boundHeight = bounds.size.height; 
      bounds.size.height = bounds.size.width; 
      bounds.size.width = boundHeight; 
      transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0); 
      transform = CGAffineTransformRotate(transform, M_PI/2.0); 
      break; 

     default: 
      [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"]; 

    } 

    UIGraphicsBeginImageContext(bounds.size); 

    CGContextRef context = UIGraphicsGetCurrentContext(); 

    if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) { 
     CGContextScaleCTM(context, -scaleRatio, scaleRatio); 
     CGContextTranslateCTM(context, -height, 0); 
    } 
    else { 
     CGContextScaleCTM(context, scaleRatio, -scaleRatio); 
     CGContextTranslateCTM(context, 0, -height); 
    } 

    CGContextConcatCTM(context, transform); 

    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef); 
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    //[self setRotatedImage:imageCopy]; 
    return imageCopy; 
} 

이 기능은 I 설정 비디오 출력 ...

AVCaptureVideoDataOutput *videoOut = [[AVCaptureVideoDataOutput alloc] init]; 
[videoOut setAlwaysDiscardsLateVideoFrames:YES]; 
[videoOut setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; // BGRA is necessary for manual preview 
dispatch_queue_t my_queue = dispatch_queue_create("com.example.subsystem.taskXYZ", NULL); 
[videoOut setSampleBufferDelegate:self queue:my_queue]; 
if ([self.captureSession canAddOutput:videoOut]) [self.captureSession addOutput:videoOut]; 
else NSLog(@"Couldn't add video output"); 
[videoOut release]; 

답변

0

에서이 최대 설정 방식을 볼 단지 배경입니다 비디오 출력에서 ​​새로 작성된 디스패치 대기열이 해제되지 않습니다.

dispatch_release(queue); 

이 함수가 너무 자주 호출되는 것을 나는 믿지 않습니다. 따라서 누출은 아마도 다른 곳에서 발생했을 것입니다. 코드를 여러 번 찾아서 다른 범인을 찾지 못했습니다 ...

누수 도구 도구로 누수를 검색해 보았습니까?

4

비슷한 문제가있었습니다. 무슨 일이 일어 났는지는 큐가 처리되지 않은 프레임으로 채워지는 것입니다. 왜냐하면 위임 객체에서 충분히 빠르게 처리하지 않았기 때문입니다.

내 용액 (한번 처리 프레임 당)을 수행 하였다 :

proctr++; 
if ((proctr % 20) == 0) { 
    deferImageProcessing = true; 
    dispatch_sync(queue, ^{ 
    [self queueFlushed]; 
    }); 
} 

- (void)queueFlushed { 
    deferImageProcessing = false; 
} 

그리고, 실제 이미지 프로세싱 코드

- (void)captureOutput:(AVCaptureOutput *)captureOutput 
    didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
    fromConnection:(AVCaptureConnection *)connection 
{ 
    if (deferImageProcessing) 
    return; 
    // do whatever else I'm doing... 
} 

본질적 큐가 비워 때까지 때때로 화상 처리를 중단.
유용하게 사용되기를 바랍니다.

+0

어디에서 코드에 proctr ++을 넣었습니까? 코드 부분? // 내가하고있는 일을 ... // 수행하고 난 다음에 했니? 나는 지금 같은 문제가있어 약 420 프레임을 처리 한 후에 충돌이 발생한다. – Davido