1

我们使用 Media Projection API 的实现工作正常。但是我们在尝试将捕获的图像写入文件时经常会丢失帧。即使所有 io 代码都在单独的线程中执行。

我们想对捕获的帧进行一些在线图像分析,因此我们不能使用 screenrecord 或类似的工具。

有没有办法从本机代码调用 Android Media Projection 方法?以获得更好的性能?

我们甚至尝试在捕获过程中不调用任何 io 操作。直到最后,我们都在记忆中。但是在 30fps 时我们仍然存在丢失帧的问题。我们怎样才能避免呢?

        try {
            image = mImageReader.acquireLatestImage();
            if (image != null) {
                Image.Plane[] planes = image.getPlanes();
                ByteBuffer buffer = planes[0].getBuffer();
                int pixelStride = planes[0].getPixelStride();
                int rowStride = planes[0].getRowStride();
                int rowPadding = rowStride - pixelStride * mWidth;
                String.valueOf(pixelStride) + " -- rowStride: " + String.valueOf(rowStride) + " rowPadding: " + String.valueOf(rowPadding));
                // create bitmap
                if(mBitmap==null || rowPadding != mRowPadding || pixelStride != mPixelStride) {
                    mRowPadding = rowPadding; mPixelStride = pixelStride;
                    mBitmap = Bitmap.createBitmap(mWidth + rowPadding / pixelStride, mHeight, Bitmap.Config.ARGB_8888);
                }
                mBitmap.copyPixelsFromBuffer(buffer);
                Bitmap myBitmap = Bitmap.createScaledBitmap(mBitmap, (mWidth + rowPadding / pixelStride) / 16, mHeight / 16, false);

                ramStorage.add(myBitmap);
4

1 回答 1

2

所有与 Bitmap 相关的代码都是本机实现的,因此将现有代码转换为使用 JNI 不会产生任何影响。我猜你正在运行内存带宽或 CPU 限制(来自复制和缩放每帧的数据),或者只是因为调度程序让其他线程运行而错过了实时截止日期。

最佳方法取决于您需要的质量水平以及应用程序正在做什么。如果您录制为视频流,而不是捕获一系列独立的帧,您将使用更少的内存和非常少的 CPU。当您仅以 30fps 的速度刻录几 MB/秒时,将数据保存在 RAM 中更为实用。如果您的应用经常更改屏幕上的每个像素,这可能无法正常工作。您的分析代码必须能够容忍宏块和矢量量化错误。

您可以通过在保存位图之前不缩放位图来权衡 CPU 与 RAM。您也可以完全避免 Bitmap,并执行您自己的复制 + 缩放操作以将 ImageReader 内容传输到 RAM 存储,一次执行这两个操作(您希望在本机代码中编写复制缩放功能)。

于 2016-03-03T17:36:00.903 回答