美文网首页
关于使用GPUImage第一次启动慢以及线程警告处理方法

关于使用GPUImage第一次启动慢以及线程警告处理方法

作者: Wayne_王 | 来源:发表于2024-08-20 14:39 被阅读0次

先总结:相机启动过慢主要是因为几个线程警告引起的,所以解决线程警告至关重要

警告截图

警告1.jpg 警告2.jpg

第一步:修改GPUImageVideoCamera.m文件中的警告

警告位置

线程报错1.jpg

解决方法

第1步:在.m文件中声明一个线程
//防止线程阻塞
@property(nonatomic) dispatch_queue_t sessionQueue;
声明.jpg
第2步:实现sessionQueue
/**
 *  创建一个队列,防止阻塞主线程
 */
- (dispatch_queue_t)sessionQueue{
    if (!_sessionQueue) {
        _sessionQueue = dispatch_queue_create("wjx_GPUImage_sessionQueue", DISPATCH_QUEUE_SERIAL);
    }
    return _sessionQueue;
}
实现.jpg
第3步:把方法添加进子线程
- (void)startCameraCapture;
{
    if (![_captureSession isRunning])
    {
        startingCaptureTime = [NSDate date];
//      [_captureSession startRunning];
        //自己添加一个子线程 操作
        __weak __typeof(self)weakSelf = self;
        dispatch_async(self.sessionQueue, ^{
            __strong __typeof(weakSelf)strongSelf = weakSelf;
            if (!strongSelf.captureSession.isRunning) {
                [strongSelf.captureSession startRunning];
            }
        });
    };
}
修改.jpg

第二步:修改GPUImageView.m文件中的警告2处

警告位置

//位置1
[[[GPUImageContext sharedImageProcessingContext] context] renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];
//位置2
CGSize currentViewSize = self.bounds.size;

解决方案

第1步:在.h文件声明两个参数并在.m文件自动编辑
//.h
@property(nonatomic)CAEAGLLayer *currentlayer;
@property(nonatomic)CGRect currentFrame;
//.m
@synthesize currentlayer;//wjx添加防止主线程卡顿
@synthesize currentFrame;//wjx添加防止主线程卡顿
h文件声明.jpg m文件编译jpg.jpg
第2步 修改“警告位置”1的报错
  • (void)commonInit方法中更改
//原文
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
eaglLayer.opaque = YES;
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
//改成
currentlayer = (CAEAGLLayer *)self.layer;
currentlayer.opaque = YES;
currentlayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
  • (void)createDisplayFramebuffer方法中更改
//原文
[[[GPUImageContext sharedImageProcessingContext] context] renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];
//改成
[[[GPUImageContext sharedImageProcessingContext] context] renderbufferStorage:GL_RENDERBUFFER fromDrawable:currentlayer];
第2步 修改“警告位置”2的报错--这有两种修改

方法1--修改会用到前面声明的currentFrame

//1.0
- (void)layoutSubviews {
    [super layoutSubviews];
    self.currentFrame = 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.
- (void)recalculateViewGeometry;
{
    runSynchronouslyOnVideoProcessingQueue(^{
        CGFloat heightScaling, widthScaling;
        
//        CGSize currentViewSize = self.bounds.size;//原文是注释掉这句
        CGSize currentViewSize = currentFrame.size;//改成这样
        
        //    CGFloat imageAspectRatio = inputImageSize.width / inputImageSize.height;
        //    CGFloat viewAspectRatio = currentViewSize.width / currentViewSize.height;
        
//        CGRect insetRect = AVMakeRectWithAspectRatioInsideRect(inputImageSize, self.bounds);
        CGRect insetRect = AVMakeRectWithAspectRatioInsideRect(inputImageSize, self.viewBounds);//原文是注释掉这句
        CGRect insetRect = AVMakeRectWithAspectRatioInsideRect(inputImageSize, currentFrame);//改成这样
      /*
       ...省略
      **/
    });
}

//3.0
- (void)createDisplayFramebuffer;
{
     /*
       ...省略
      **/
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, displayRenderbuffer);
    
    GLuint framebufferCreationStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    NSAssert(framebufferCreationStatus == GL_FRAMEBUFFER_COMPLETE, @"Failure with display framebuffer generation for display of size: %f, %f", self.bounds.size.width, self.bounds.size.height);
    //boundsSizeAtFrameBufferEpoch = self.bounds.size;//原文是注释掉这句
    boundsSizeAtFrameBufferEpoch = currentFrame.size;//改成这样
}

方法2--修改会不会用到前面声明的currentFrame--只需要--判断是否为主线程

//1.先把recalculateViewGeometry方法中的代码提出来-重写一个函数
- (void)wjx_recalculateViewGeometryWithSize:(CGSize)size{
    runSynchronouslyOnVideoProcessingQueue(^{
        CGFloat heightScaling, widthScaling;
        
        CGSize currentViewSize = size;
        
        //    CGFloat imageAspectRatio = inputImageSize.width / inputImageSize.height;
        //    CGFloat viewAspectRatio = currentViewSize.width / currentViewSize.height;
        
        CGRect insetRect = AVMakeRectWithAspectRatioInsideRect(inputImageSize, 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,
//    };
}

//2.修改recalculateViewGeometry
- (void)recalculateViewGeometry;
{
    NSLog(@"Is main thread: %@", [NSThread isMainThread] ? @"YES" : @"NO");
    if ([NSThread isMainThread] == NO) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self wjx_recalculateViewGeometryWithSize:self.bounds.size];
        });
    } else {
        [self wjx_recalculateViewGeometryWithSize:self.bounds.size];
    }
}

本文主要引用两篇文章做了汇总感谢
【iOS紫色警告】GPUImage启动摄像头耗时
GPUImage 子线程访问 UI 的输出警告处理

相关文章

  • 多线程网络03

    1 多图下载综合案例 包含数据展示、缓存处理、子线程下载图片以及内存警告处理 2 SDWebImage的使用和说明...

  • 如何区别线程的start方法和run方法

    1. 使用run方法启动线程 查看执行结果: 2. 使用start方法启动线程 查看执行结果: 结果分析 调用ru...

  • Kafka 消费者心跳线程源码解析

    kafka消费者在消费消息时,分为心跳线程和用户线程(处理消息的线程) 消费消息poll方法 我们在第一次启动消费...

  • GPUImage学习---02:GPUImage的处理过程和类结

    GPUImage处理画面原理 GPUImage采用链式方式来处理画面,通过addTarget:方法为链条添加每个环...

  • { 1 }CPP_线程管理的基础

    一,启动线程 1. 使用C++线程库启动线程,即为构造std::thread对象: std::thread构造方法...

  • Java线程的启动和终止

    在Java中我们启动线程都是调用Thread类中的start()方法来启动,当线程处理完run()方法里面的逻辑后...

  • Android消息机制分析

    异步消息处理线程 对于普通的线程而言,执行完run()方法内的代码后线程就结束。而异步消息处理线程是指,线程启动后...

  • JAVA进程和线程-day01

    A 进程 线程 线程和进程的区别 线程使用的场合 创建线程的方法 并发原理 使用Runnable创建并启动线程 线...

  • GPUImage

    1.添加GPUImage静态库 关于导入GPUimage到工程已经简单使用:只能用于真机关于GPUImage的导入...

  • redis-07-redis启动警告处理

    [TOC] 在redis-3.2.8安装完之后启动过程中可能会有警告信息。 以下是处理方法: 警告1 临时解决方案...

网友评论

      本文标题:关于使用GPUImage第一次启动慢以及线程警告处理方法

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