• 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手机测试时又没这个问题,是否是因为手米手机速度快,格式转换快,所以没耽误帧率?

  • 相关阅读:
    2022-08-18 多线程安全的Parallel Hashmap
    [unity] c# 扩展知识点其一 【个人复习笔记/有不足之处欢迎斧正/侵删】
    Spring注解@Qualifier的详细用法你知道几种「扩展点实战系列」- 第444篇
    Spring – 记录传入请求
    2023年全国职业院校技能大赛(高职组)“云计算应用”赛项赛卷7(私有云)
    Java 内部类
    Flink源码篇【1】Flink 1.15.0源码编译
    在CentOS 7中手工打造和运行xml文件配置的Servlet,然后使用curl、浏览器、telnet等三种工具各自测试
    温度及pH敏感性聚乙烯醇/羧甲基壳聚糖水凝胶/金银花多糖/薄荷多糖/O-羧甲基壳聚糖水凝胶
    【图像去噪】【TGV 正则器的快速计算方法】通过FFT的总(广义)变化进行图像去噪(Matlab代码实现)
  • 原文地址:https://blog.csdn.net/android_cai_niao/article/details/126019901