带有 MediaProjection 的 android.media.ImageReader 在 Android 14 上卡住了

问题描述 投票:0回答:1

我正在使用 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)
}
android screen-capture webrtc-android image-reader mediaprojection
1个回答
0
投票

我有同样的问题,mediaprojection 在 Android 14 上停止,没有任何错误,但我没有解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.