• setPreviewCallbackWithBuffer的出帧效率会变低


    下面代码实现一个无预览的视频采集,并且每10秒统计一下帧率:

    class MainActivity : AppCompatActivity() {
    
        private lateinit var camera: Camera
        private val surfaceTexture = SurfaceTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES)
        private val width = 1920
        private val height = 1080
        private var fps = 0
        private var start = 0L
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            println("width = $width height = $height")
            camera = Camera.open()
            camera.parameters = camera.parameters.apply {
                previewFormat = ImageFormat.NV21
                setPreviewSize(width, height)
            }
    
            camera.setPreviewTexture(surfaceTexture)
            camera.setPreviewCallback { data, camera ->
                fps++
                val current = System.currentTimeMillis()
                if (start == 0L) {
                    start = current
                }
                if (current - start >= 10000) {
                    println("帧速:${fps}帧/10秒")
                    fps = 0
                    start = current
                }
            }
            camera.startPreview()
        }
    
        override fun onDestroy() {
            super.onDestroy()
            camera.setPreviewCallback(null)
            camera.stopPreview()
            camera.release()
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    在小米11 pro运行效果如下:

    width = 1920 height = 1080
    帧速:301/10秒
    帧速:300/10秒
    帧速:300/10秒
    帧速:300/10秒
    帧速:301/10秒
    帧速:300/10秒
    帧速:300/10
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    平均帧速为30帧/秒。听闻使用缓冲区可以提高效率,于是我们把视频采集改为使用缓冲的方式,如下:

    class MainActivity : AppCompatActivity() {
    
        private lateinit var camera: Camera
        private val surfaceTexture = SurfaceTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES)
        private val width = 1920
        private val height = 1080
        private val callbackBuffer = ByteArray((width * height * 3) shr 1)
        private var fps = 0
        private var start = 0L
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            println("width = $width height = $height")
            camera = Camera.open()
            camera.parameters = camera.parameters.apply {
                previewFormat = ImageFormat.NV21
                setPreviewSize(width, height)
            }
    
            camera.setPreviewTexture(surfaceTexture)
            camera.addCallbackBuffer(callbackBuffer)
            camera.setPreviewCallbackWithBuffer { data, camera ->
                fps++
                val current = System.currentTimeMillis()
                if (start == 0L) {
                    start = current
                }
                if (current - start >= 10000) {
                    println("帧速:${fps}帧/10秒")
                    fps = 0
                    start = current
                }
                camera.addCallbackBuffer(callbackBuffer)
            }
            camera.startPreview()
        }
    
        override fun onDestroy() {
            super.onDestroy()
            camera.setPreviewCallback(null)
            camera.stopPreview()
            camera.release()
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    在小米11 pro运行结果如下:

    width = 1920 height = 1080
    帧速:276/10秒
    帧速:293/10秒
    帧速:298/10秒
    帧速:299/10秒
    帧速:295/10秒
    帧速:297/10
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    可以看到,使用了缓冲之后,帧率下降了,效率并没有提高,只能说更省内存了。在公司的手机上测试效果相差更明显,如没使用缓冲的测试情况:

    width = 1920 height = 1080
    帧速:189/10秒
    帧速:249/10秒
    帧速:247/10秒
    帧速:250/10秒
    帧速:173/10秒
    帧速:162/10秒
    帧速:147/10秒
    帧速:173/10
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    使用了缓冲后的测试情况:

    width = 1920 height = 1080
    帧速:133/10秒
    帧速:181/10秒
    帧速:133/10秒
    帧速:129/10秒
    帧速:141/10秒
    帧速:139/10秒
    帧速:133/10秒
    帧速:135/10
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    可以看到,使用了缓冲后帧速明显下降。如果使用YV12格式,

    基于这个测试结果,在我们公司的项目开发上我就没有使用缓冲区了,因为我们开发的项目是运行在一个特别的Android设备上,这个Android设备一启动就只运行我们的一个应用,没有其它应用,所以多消耗点内存也没事,反正内存是够用的。

    对于格式的选择上也有讲究的,比如在公司的手机上,使用NV21格式,宽640,高480,使用缓冲区,测试结果如下:

    width = 640 height = 480
    帧速:192/10秒
    帧速:240/10秒
    帧速:236/10秒
    帧速:239/10秒
    帧速:238/10秒
    帧速:238/10
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    帧率还行,然后我们只改一个格式,把NV21改成YV12,测试结果如下:

    width = 640 height = 480
    帧速:181/10秒
    帧速:182/10秒
    帧速:179/10秒
    帧速:177/10
    • 1
    • 2
    • 3
    • 4
    • 5

    可以看到,就改了一个格式,帧率下降明显,是否可以认为这台设备的摄像头采集就是用NV21采集的,当我们使用YV12格式时,框架需要进行NV21 到 YV12格式的转换操作,所以导致帧率下降?当我使用小米11 pro手机测试时又没这个问题,是否是因为手米手机速度快,格式转换快,所以没耽误帧率?

  • 相关阅读:
    手写RPC Day3 服务注册
    SSM出租车查询系统 毕业设计-附源码220915
    Canvas录制视频
    MySQL 教程 1.1
    vue + canvas 实现九宮格手势解锁器
    斐波那契数列二(马蹄集)
    UE4 Ultradynamicsky进行地面交互
    到站上海!见证这座零碳园区的绿色低碳新选择
    2022年最新《Java八股文面试宝典》全网独一份!(效率最高、知识最新、包含各个技术栈)
    浏览器缓存机制
  • 原文地址:https://blog.csdn.net/android_cai_niao/article/details/126019901