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

标签 ios xcode cocoa-touch cocoa avfoundation

我正在利用 AVFoundation 将自定义相机集成到我的应用程序中...问题是,由于内存压力,我遇到了罕见但仍在发生的崩溃,我不确定为什么,因为我使用 ARC,崩溃时 Xcode 中的内存只有 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];
        }
    }

最佳答案

你在哪里设置 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];
    }

}

关于ios - AVFoundation 自定义相机导致崩溃/内存压力?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24419446/

相关文章:

ios - 如何处理iOS中的多个API调用?

ios - 文件存在于 iCloud 中,但 query.resultCount = 0

c++ - Xcode:malloc 大小似乎无关紧要

iphone - 按升序对 nsarray 进行排序

ios - 仅在用户第一次打开应用程序时加载 View Controller

ios - 修改 getter 以避免 NSNull

ios - 自定义委托(delegate)问题

iphone - Objective-C : How do I draw lines with alpha in quad curve

ios - prepareForSegue 中的分配 false

objective-c - 详细信息 View 上的不同文本