美文网首页
iOS 记GPUImage框架使用问题

iOS 记GPUImage框架使用问题

作者: iOS_July | 来源:发表于2022-01-15 15:34 被阅读0次

1、第一次打开GPUImage的相机很慢很慢,启动就是很慢......

不出意外的话,这里项目是报了一个紫色感叹号的内存泄露问题。解决方法也很简单:
1、在GPUImageView.m里,定义一个属性viewBounds,来记录做中转。

///解决首次启动很慢的问题
@property (nonatomic, assign) CGRect viewBounds;

2、在初始方法里做记录。

- (id)initWithFrame:(CGRect)frame
{
    if (!(self = [super initWithFrame:frame]))
    {
        return nil;
    }
    
    //第一次启动很慢
    self.viewBounds = self.bounds;
    [self commonInit];
    
    return self;
}

3、修改 recalculateViewGeometry 方法,将self.bounds.size替换为我们定义的self.viewBounds.size

- (void)recalculateViewGeometry;
{
    runSynchronouslyOnVideoProcessingQueue(^{
        CGFloat heightScaling, widthScaling;
        
        CGSize currentViewSize = self.viewBounds.size;//self.bounds.size;
        
        //    CGFloat imageAspectRatio = inputImageSize.width / inputImageSize.height;
        //    CGFloat viewAspectRatio = currentViewSize.width / currentViewSize.height;
        
        CGRect insetRect = AVMakeRectWithAspectRatioInsideRect(inputImageSize, self.viewBounds);//self.bounds
        
        switch(_fillMode)
        {
            case kGPUImageFillModeStretch:
            {
                widthScaling = 1.0;
                heightScaling = 1.0;
            }; break;
            case kGPUImageFillModePreserveAspectRatio:
            {
                widthScaling = insetRect.size.width / currentViewSize.width;
                heightScaling = insetRect.size.height / currentViewSize.height;
            }; break;
            case kGPUImageFillModePreserveAspectRatioAndFill:
            {
                //            CGFloat widthHolder = insetRect.size.width / currentViewSize.width;
                widthScaling = currentViewSize.height / insetRect.size.height;
                heightScaling = currentViewSize.width / insetRect.size.width;
            }; break;
        }
        
        imageVertices[0] = -widthScaling;
        imageVertices[1] = -heightScaling;
        imageVertices[2] = widthScaling;
        imageVertices[3] = -heightScaling;
        imageVertices[4] = -widthScaling;
        imageVertices[5] = heightScaling;
        imageVertices[6] = widthScaling;
        imageVertices[7] = heightScaling;
    });
    
//    static const GLfloat imageVertices[] = {
//        -1.0f, -1.0f,
//        1.0f, -1.0f,
//        -1.0f,  1.0f,
//        1.0f,  1.0f,
//    };
}

4、如果你有切换比例,进行拍照等操作,需要在GPUImageView.m 的 layoutSubviews里更新我们自定义的属性,否则你切换画幅比例之后,页面还是以前的预览视图大小。

- (void)layoutSubviews {
    [super layoutSubviews];
    
    //第一次启动很慢
    self.viewBounds = self.bounds;
    
    // The frame buffer needs to be trashed and re-created when the view size changes.
    if (!CGSizeEqualToSize(self.bounds.size, boundsSizeAtFrameBufferEpoch) &&
        !CGSizeEqualToSize(self.bounds.size, CGSizeZero)) {
        runSynchronouslyOnVideoProcessingQueue(^{
            [self destroyDisplayFramebuffer];
            [self createDisplayFramebuffer];
            [self recalculateViewGeometry];
        });
    }
}

2、录制视频时崩溃

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Tried to overrelease a framebuffer, did you forget to call -useNextFrameForImageCapture before using -imageFromCurrentFramebuffer?'

是因为 framebufferReferenceCount的值小于0,这里是GPUImage对buffer的缓存处理,简单的解决办法是在源文件GPUImageFramebuffer.m 中 unlock方法添加一个判断:

- (void)unlock;
{
    if (referenceCountingDisabled)
    {
        return;
    }
    //此处为手动添加 修改
    if (framebufferReferenceCount <1) {
       return;
    }
    NSAssert(framebufferReferenceCount > 0, @"Tried to overrelease a framebuffer, did you forget to call -useNextFrameForImageCapture before using -imageFromCurrentFramebuffer?");
    framebufferReferenceCount--;
    if (framebufferReferenceCount < 1)
    {
        [[GPUImageContext sharedFramebufferCache] returnFramebufferToCache:self];
    }
}

3、录制视频出现首帧黑屏、卡帧、丢帧的情况

这是因为自己在结束视频录制时,释放时机不对,导致的问题。解决方法很简单,不要直接调用finishRecordingWithCompletionHandler,
而是在finishRecordingWithCompletionHandler的回调里去写结束的逻辑

//MARK: - 结束录制视频
/// 结束录制视频
- (void)endRecording {
    WEAK_SELF;
    [self.movieWriter finishRecordingWithCompletionHandler:^{
        STRONG_SELF;
        dispatch_async(dispatch_get_main_queue(), ^{
            
            strongSelf.isRecording = NO;
            [strongSelf.cameraFilter setFrameProcessingCompletionBlock:nil];
            [strongSelf.blendFilter removeTarget:strongSelf.movieWriter];
            [strongSelf.imageElement removeTarget:strongSelf.blendFilter];
            [strongSelf.cameraFilter removeTarget:strongSelf.blendFilter];
            strongSelf.blendFilter    = nil;
            strongSelf.imageElement   = nil;
            strongSelf.movieWriter    = nil;
        });
    }];

}

4、打开手机旋转锁定后,横屏拍照处理失效

这个bug很隐秘,因为我自己手机一直是锁定的,做完横屏的处理之后,测试机还是有问题,但我的没有问题,苦苦找寻,才发现是屏幕锁定被打开了。这里我采用的方式是将输出都做统一的输出矫正,解决方法:
1、找到GPUImageOutput.h,定义一个暴露给外界的方法imageFromCurrentFramebuffer2

/// 手动增加的方法,防止打开手机屏幕旋转锁定后,拍照出现错乱的bug
- (UIImage *)imageFromCurrentFramebuffer2;

2、在GPUImageOutput.m里进行方法实现

/// 手动增加的方法,防止打开手机屏幕旋转锁定后,拍照出现错乱的bug
- (UIImage *)imageFromCurrentFramebuffer2
{
    return [self imageFromCurrentFramebufferWithOrientation:UIImageOrientationUp];
}

3、我是使用的GPUImageStillCamera来定义的相机,在GPUImageStillCamera.m里,找到我调用的拍照方法- (void)capturePhotoAsImageProcessedUpToFilter:(GPUImageOutput<GPUImageInput> *)finalFilterInChain withCompletionHandler:(void (^)(UIImage *processedImage, NSError *error))block,进行修改

- (void)capturePhotoAsImageProcessedUpToFilter:(GPUImageOutput<GPUImageInput> *)finalFilterInChain withCompletionHandler:(void (^)(UIImage *processedImage, NSError *error))block;
{
    [self capturePhotoProcessedUpToFilter:finalFilterInChain withImageOnGPUHandler:^(NSError *error) {
        UIImage *filteredPhoto = nil;

        if(!error){
            filteredPhoto = [finalFilterInChain imageFromCurrentFramebuffer2];
            //[finalFilterInChain imageFromCurrentFramebuffer];
        }
        dispatch_semaphore_signal(frameRenderingSemaphore);

        block(filteredPhoto, error);
    }];
}

相关文章

网友评论

      本文标题:iOS 记GPUImage框架使用问题

      本文链接:https://www.haomeiwen.com/subject/yfithrtx.html