2025年3月25日 星期二 甲辰(龙)年 月廿四 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > 安卓(android)开发

setPreviewCallbackWithBuffer的出帧效率会变低

时间:02-09来源:作者:点击数:49

下面代码实现一个无预览的视频采集,并且每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()
  • }
  • }

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

  • width = 1920 height = 1080
  • 帧速:301帧/10
  • 帧速:300帧/10
  • 帧速:300帧/10
  • 帧速:300帧/10
  • 帧速:301帧/10
  • 帧速:300帧/10
  • 帧速:300帧/10

平均帧速为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()
  • }
  • }

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

  • width = 1920 height = 1080
  • 帧速:276帧/10
  • 帧速:293帧/10
  • 帧速:298帧/10
  • 帧速:299帧/10
  • 帧速:295帧/10
  • 帧速:297帧/10

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

  • width = 1920 height = 1080
  • 帧速:189帧/10
  • 帧速:249帧/10
  • 帧速:247帧/10
  • 帧速:250帧/10
  • 帧速:173帧/10
  • 帧速:162帧/10
  • 帧速:147帧/10
  • 帧速:173帧/10

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

  • width = 1920 height = 1080
  • 帧速:133帧/10
  • 帧速:181帧/10
  • 帧速:133帧/10
  • 帧速:129帧/10
  • 帧速:141帧/10
  • 帧速:139帧/10
  • 帧速:133帧/10
  • 帧速:135帧/10

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

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

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

  • width = 640 height = 480
  • 帧速:192帧/10
  • 帧速:240帧/10
  • 帧速:236帧/10
  • 帧速:239帧/10
  • 帧速:238帧/10
  • 帧速:238帧/10

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

  • width = 640 height = 480
  • 帧速:181帧/10
  • 帧速:182帧/10
  • 帧速:179帧/10
  • 帧速:177帧/10

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

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门