AVFoundation自定义相机导致崩溃/内存压力?

时间:2014-06-25 22:10:31

标签: ios xcode cocoa-touch cocoa avfoundation

我正在利用AVFoundation将自定义相机集成到我的应用程序中...问题是,由于内存压力,我得到了罕见但仍然发生的崩溃,我不是确定为什么我使用ARC,而Xcode中的Memory在崩溃时只有大约20mb?发生了什么事?

这是我的代码

- (void)setupCamera
    {
        self.session = [[AVCaptureSession alloc] init];
        [self.session setSessionPreset:AVCaptureSessionPresetPhoto];

        AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
        if ([self.session canAddInput:input]) {
            [self.session addInput:input];
        }

        AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc] init];
        if ([self.session canAddOutput:output]) {
            output.videoSettings = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey];
            [self.session addOutput:output];
            [output setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
        }

        self.preview = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
        [self.preview setVideoGravity:AVLayerVideoGravityResizeAspectFill];
        [self.preview setFrame:self.cameraView.frame];

        CALayer *cameraLayer = self.cameraView.layer;
        [cameraLayer setMasksToBounds:YES];
        [cameraLayer addSublayer:self.preview];

        for (AVCaptureConnection *connection in output.connections) {
            if (connection.supportsVideoOrientation) {
                [connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
            }
        }

        NSURL *shutterUrl = [[NSURL alloc] initWithString:[[NSBundle mainBundle] pathForResource: @"shutter" ofType: @"wav"]];
        self.shutterPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:shutterUrl error:nil];
        [self.shutterPlayer prepareToPlay];
    }

    - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
    {
        if (self.doCapture) {
            self.doCapture = NO;

            [self.shutterPlayer setCurrentTime:0];
            [self.shutterPlayer play];

            CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
            CVPixelBufferLockBaseAddress(imageBuffer, 0);
            void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);

            size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
            size_t width = CVPixelBufferGetWidth(imageBuffer);
            size_t height = CVPixelBufferGetHeight(imageBuffer);

            CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
            CGContextRef rawContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
            CGImageRef quartzImage = CGBitmapContextCreateImage(rawContext);
            CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
            CGContextRelease(rawContext);
            CGColorSpaceRelease(colorSpace);

            UIImage *rawImage = [UIImage imageWithCGImage:quartzImage];
            CGImageRelease(quartzImage);

            float rawWidth = rawImage.size.width;
            float rawHeight = rawImage.size.height;
            CGRect cropRect = (rawHeight > rawWidth) ? CGRectMake(0, (rawHeight - rawWidth) / 2, rawWidth, rawWidth) : CGRectMake((rawWidth - rawHeight) / 2, 0, rawHeight, rawHeight);
            CGImageRef croppedImageRef = CGImageCreateWithImageInRect([rawImage CGImage], cropRect);

            UIImage *croppedImage = [UIImage imageWithCGImage:croppedImageRef];
            CGImageRelease(croppedImageRef);

            [self saveImage:croppedImage];
        }
    }

    - (void)saveImage:(UIImage *)image
    {
        [self.capturedImages addObject:image];

        NSArray *scrollItemXIB = [[NSBundle mainBundle] loadNibNamed:@"SellPreviewImagesScrollItemView" owner:self options:nil];
        UIView *scrollItemView = [scrollItemXIB lastObject];

        UIImageView *previewImage = (UIImageView *)[scrollItemView viewWithTag:PREVIEW_IMAGES_SCROLL_ITEM_TAG_IMAGE];
        previewImage.image = image;

        UIButton *deleteButton = (UIButton *)[scrollItemView viewWithTag:PREVIEW_IMAGES_SCROLL_ITEM_TAG_BADGE_BUTTON];
        [deleteButton addTarget:self action:@selector(deleteImage:) forControlEvents:UIControlEventTouchUpInside];

        UIButton *previewButton = (UIButton *)[scrollItemView viewWithTag:PREVIEW_IMAGES_SCROLL_ITEM_TAG_BUTTON];
        [previewButton addTarget:self action:@selector(previewImage:) forControlEvents:UIControlEventTouchUpInside];

        [self addItemToScroll:scrollItemView];
        [self checkCapturedImagesLimit];

        if ([self.capturedImages count] == 1) {
            [self makeCoverPhoto:[self.capturedImages objectAtIndex:0]];
            [self cells:self.previewImagesToggle setHidden:NO];
            [self reloadDataAnimated:YES];
        }
    }

2 个答案:

答案 0 :(得分:0)

你设置self.doCapture = true的地方?看起来你为临时对象分配了大量内存。尝试使用@autoreleasepool指令:

@autoreleasepool {
    self.doCapture = NO;

    [self.shutterPlayer setCurrentTime:0];
    [self.shutterPlayer play];

       ...

    if ([self.capturedImages count] == 1) {
        [self makeCoverPhoto:[self.capturedImages objectAtIndex:0]];
        [self cells:self.previewImagesToggle setHidden:NO];
        [self reloadDataAnimated:YES];
    }

}

答案 1 :(得分:0)

我想我可能遇到了同样的问题("由于内存压力而终止"),我刚刚将AVCaptureSession的设置从viewDidAppear更改为ViewDidLoad。它在iPad上增长到100mb左右,现在最高可达14mb,顶部有大图像叠加。