2010-07-26 10 views
6

Ich nehme Video und konvertiere es in eine CGImage, um die Verarbeitung darauf zu tun. Es wird für ~ 10 Sekunden funktionieren, Speicherwarnung erhalten und dann abstürzen (normalerweise sagt es, dass Datenformatierer vorübergehend nicht verfügbar waren). Kann mir jemand helfen, das Problem zu lösen?iPhone: AVCaptureSession Capture-Ausgabe Absturz (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; 



} 

Code, um das Bild zu verwandeln ....

- (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; 
} 

Diese Funktion ist nur Hintergrund zu sehen, wie ich ein Setup des Videoausgang ...

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]; 

Antwort

0

bei der Einrichtung des Videoausgabe wird die neu erstellte Dispatch Queue nicht freigegeben. Sie können es mit

freigeben. Aber ich glaube nicht, dass diese Funktion zu oft aufgerufen wird, so dass das Leck wahrscheinlich anderswo entsteht. Durchsuchen Sie Ihren Code mehrmals, konnten keine anderen Täter finden ...

Haben Sie versucht, das Leck mit dem Leaks Instrument Tool zu suchen?

4

Ich hatte ein ähnliches Problem. Was passierte, war, dass die Warteschlange sich mit nicht verarbeiteten Frames füllte, weil ich im Delegate-Objekt nicht schnell genug verarbeitete.

Meine Lösung war, zu tun (einmal pro verarbeitete Rahmen):

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

- (void)queueFlushed { 
    deferImageProcessing = false; 
} 

Dann wird in dem aktuellen Bildverarbeitungscode

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

Im Wesentlichen uns gelegentlich Bildverarbeitung auszusetzen, bis die Warteschlange leert.
Ich hoffe, das ist nützlich.

+0

Wo in Ihrem Code haben Sie den proctr ++; Teil des Codes? Hast du es nach dem // gemacht, was ich sonst mache ... Sektion? Ich habe jetzt das gleiche Problem, Abstürze nach der Verarbeitung von etwa 420 Frames. – Davido

Verwandte Themen