zoukankan      html  css  js  c++  java
  • GPUImage实现摄像头暂停

    GPUImage相信很多开发者都用过,其本身也是十分简单易用,因此对于GPUImage的基本用法不再赘述。

    最近在使用GPUImage时要实现摄像时暂停和继续的功能,但GPUImage本身并没有提供相关的接口。查看GPUImageVideoCamera 中的相关代码,可以发现

    - (void)pauseCameraCapture;方法。但这个方法会令GPUImage显示的摄像头捕捉的画面也暂停,这显然不是一个好的方案。

    但- (void)pauseCameraCapture;这个方法却能给我们带来解决问题的思路。查看GPUImage源代码:

    - (void)pauseCameraCapture;

    {

        capturePaused = YES;

    }

     在这里只是简单地设置了一个暂停的标志。那这个标志在什么地方用到呢。继续看代码:

    - (void)processVideoSampleBuffer:(CMSampleBufferRef)sampleBuffer;

    {

        if (capturePaused)

        {

            return;

        }

     .....

    }

    在处理视频帧的地方,如果暂停了就直接返回,用这种方法来实现暂停。

    显然我们可以采用类似的方法来处理,但是首先我们要找到在哪里处理。如果使用过GPUImageVideoCamera,大致都会知道视频帧的流向。

    如图,首先是GPUImageVideoCamera获取视频帧,将其传给filter,然后filter再将视频帧传给GPUImageView和

    。前者用来显示摄像头捕捉到的图像,后者用来保存视频。

    我们要实现暂停(显示的图像不暂停)显然只能在GPUImageMovieWriter这个环节来实现了。

    继续看代码,找到GPUImageMovieWriter这个类中处理视频帧的的方法。

    - (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex;

    要怎么改写看个人具体情况了,可以直接修改,继承或者用category。本人采用的是继承的方式。

    增加个标志,暂停就直接返回,否则调用父类的方法处理。看起来好像没问题,写个demo测试一下,发现视频暂停后,到继续的那段时间里不是直接跳过,而是

    一直显示暂停时的那一帧图像。这是因为视频帧是带有时间戳的,虽然丢弃了暂停时的视频帧,但是时间戳还是原来的值,所以就出现了这种奇怪的情况。

    继续修改时间戳:

    - (void)configure{

        _timeOffset = CMTimeMake(0, 1);

        _isDisCount = NO;

        _isPause = NO;

        _isAudioOn = YES;

        _offSet = kCMTimeZero;

    }

    - (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex{

        if (_isPause) {

            return;

        }

        

        if (_isDisCount) {

            _isDisCount = NO;

             _offSet = CMTimeSubtract(frameTime, _last);

            if (_offSet.value > 0) {

                _timeOffset = CMTimeAdd(_timeOffset, _offSet);

            }

        }

        

        _last = frameTime;

        frameTime = CMTimeSubtract(frameTime, _timeOffset);

        [super newFrameReadyAtTime:frameTime atIndex:textureIndex];

    }

    改完再测试一下,暂停和恢复摄像正常了,没有什么问题。但是,视频末尾出现了有一小段时间播放最后一帧的情况,这是什么问题。

    如果你录音声音正常的话就可以听到最后一段视频卡住了,但音频还是正常播放的。这是因为,我们只处理了图像帧,而没有处理音频

    的缘故。

    找到相关的方法,简单地return一下就好了。

    - (void)processAudioBuffer:(CMSampleBufferRef)audioBuffer

    {

      

        if (_isPause) {

            return;

        }

        

        [super processAudioBuffer:audioBuffer];

    }

      大概是GPUImageMovieWriter中处理了,音频会被按照顺序直接连接在一起,修改时间没用。

    所以,如果想实现音频暂停(按照时间播放,中间有一段没声音)的话会比较麻烦。一种是可以记录暂停时间,在录音完之后进行剪辑。

    另一种可以插入空的音频帧(没试过)。

  • 相关阅读:
    基于spark实现表的join操作
    关于IO的一些数字
    scala的REPL shell的调用
    搭建eclipse+maven+scala-ide的scala web开发环境
    Apache Mesos总体架构
    spark下测试akka的分布式通讯功能
    akka创建actor时报错:IllegalArgumentException: no matching constructor found on class $iwC$$iwC$$iwC$$iwC$
    akka构建简单分布式应用
    Memcached 工作原理
    分析Redis架构设计
  • 原文地址:https://www.cnblogs.com/bigly/p/5795002.html
Copyright © 2011-2022 走看看