【发布时间】:2021-01-29 15:10:31
【问题描述】:
我正在编写一个 Android 应用程序,其中本机线程以大约 60 fps 的速度不断生成图像帧(作为原始像素数据),然后应该显示在 SurfaceView 中。目前线程直接将像素数据写入到原生线程和JVM共享的ByteBuffer,然后通过JNI调用回调通知JVM端一帧准备好;然后将缓冲区读入Bitmap 并在SurfaceView 上绘制。我的代码大致是这样的(完整的源代码太大而无法共享):
// this is a call into native code that retrieves
// the width and height of the frame in pixels
// returns something on the order of 320×200
private external fun getFrameDimensions(): (Int, Int)
// a direct ByteBuffer shared between the JVM and the native thread
private val frameBuffer: ByteBuffer
private fun getFrame(): Bitmap {
val (width, height) = getFrameDimensions()
return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888).apply {
setHasAlpha(false)
copyPixelsFromBuffer(frameBuffer.apply {
order(ByteOrder.nativeOrder())
rewind()
})
}
}
// the SurfaceView widget which should display the image
private lateinit var surfaceView: SurfaceView
private val SCALE = 8
// callback invoked by the native thread
public fun onFrameReady() {
val canvas: Canvas = surfaceView.holder.lockCanvas() ?: return
val bitmap = getFrame()
try {
canvas.drawBitmap(bitmap.scale(
bitmap.width * SCALE,
bitmap.height * SCALE),
0.0f, 0.0f, null
)
} finally {
holder.unlockCanvasAndPost(canvas)
}
}
好消息是上述方法有效:屏幕以大致预期的帧速率更新。然而,性能真的很差,以至于应用程序锁定:它停止响应例如按下 ◁ 按钮,最终会弹出 ANR 消息。显然我做错了什么,但我不太清楚到底是什么。
有没有办法让上面的运行更快?最好我想避免编写不必要的本机代码。我特别想避免将任何特定于 Android 的东西放在本机方面。
【问题讨论】:
-
我知道你不能分享完整的源代码,但我建议在 Github 上创建一个简单的演示项目,我们可以轻松地重现这个问题。
标签: android performance kotlin surfaceview image-rendering