我正在使用 MediaProjection 与 WebRTC 进行屏幕共享。将我的 Pixel 7 Pro 更新到 Android 14 后,它不再正确捕获帧。在较旧的 Android 版本上,它可以正常运行,没有任何问题。
行为: 屏幕捕获开始,我收到几帧 (40-50),但随后没有捕获新的帧。没有错误或“停止”回调; onImageAvailableListener 回调只是停止被调用。
预期行为: 当屏幕内容发生变化时,会持续捕获新帧
为了进一步调查,我创建了一个空项目,其中包含启动屏幕捕获所需的最少代码。代码如下。
我发现这个问题似乎与ImageReader有关。将 SurfaceView 附加到 VirtualDisplay 时,帧会一致地传递。
有人在 Android 14 上遇到过类似的 MediaProjection 问题吗?这个问题有已知的解决方法或解决方案吗?
class MediaProjectionCapturer(private val mediaProjectionData: Intent) {
private var imageCounter = 0
private val imageReaderMaxImages = 2
private lateinit var virtualDisplay: VirtualDisplay
private val listenerHandler : Handler
init {
val listenerHandlerThread = HandlerThread(TAG)
listenerHandlerThread.start()
listenerHandler = Handler(listenerHandlerThread.looper)
}
fun start(context: Context, displaySurface: Surface?) { // ❗❗❗ <- passing surfaceView.holder.surface if not null
val screenConfig = loadScreenConfig(context)
val surface = if (displaySurface != null) {
displaySurface // <- ❗❗❗ surfaceView.holder.surface
} else {
val reader = ImageReader.newInstance(
screenConfig.width,
screenConfig.height,
PixelFormat.RGBA_8888,
imageReaderMaxImages
)
val imageAvailableListener = onImageAvailableListener()
reader.setOnImageAvailableListener(imageAvailableListener, listenerHandler)
reader.surface // <- ❗❗❗imageReader surface
}
val display = createVirtualDisplay(
context = context,
screenConfig = screenConfig,
displaySurface = surface // <- ❗❗❗ Setting the surface to VirtualDisplay
)
virtualDisplay = display
}
private fun onImageAvailableListener () = ImageReader.OnImageAvailableListener { imageReader ->
Log.d("ImageAvailable", "Delivered new image $imageCounter")
imageReader.acquireNextImage()?.close()
++imageCounter
}
private fun createVirtualDisplay(
context: Context,
screenConfig: ScreenConfig,
displaySurface: Surface
): VirtualDisplay {
val projectionManager = context.getSystemService(
Context.MEDIA_PROJECTION_SERVICE
) as MediaProjectionManager
val projection = projectionManager.getMediaProjection(RESULT_OK, mediaProjectionData)
projection.registerCallback(
object : MediaProjection.Callback() {
override fun onStop() {
onStop()
}
}, listenerHandler
)
return projection.createVirtualDisplay(
TAG,
screenConfig.width,
screenConfig.height,
screenConfig.dpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
displaySurface,
null,
null
)
}
private fun loadScreenConfig(context: Context): ScreenConfig {
val metrics: DisplayMetrics
val width: Int
val height: Int
val dpi: Int
val windowManager = context.getSystemService(WindowManager::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val windowMetrics = windowManager.currentWindowMetrics
width = windowMetrics.bounds.width()
height = windowMetrics.bounds.height()
dpi = context.resources.displayMetrics.densityDpi
} else {
metrics = DisplayMetrics()
@Suppress("DEPRECATION")
windowManager.defaultDisplay.getMetrics(metrics)
width = metrics.widthPixels
height = metrics.heightPixels
dpi = metrics.densityDpi
}
return ScreenConfig(width, height, dpi)
}
private data class ScreenConfig(val width: Int, val height: Int, val dpi: Int)
}
我有同样的问题,mediaprojection 在 Android 14 上停止,没有任何错误,但我没有解决方案。