0

我使用 MediaProjection api 以及 VirtualDisplay 和 ImageReader 来共享屏幕。下面是创建 VirtualDisplay 和 ImageReader 的方法:

private void createVirtualDisplay(Activity mContext) {


        final DisplayMetrics metrics = new DisplayMetrics();
        mContext.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);

        final int width = metrics.widthPixels;
        final int height = metrics.heightPixels;
        final int densityDpi = metrics.densityDpi;
        final int MAX_IMAGES = 2;

        mWidth = width; // 1080
        mHeight = height; // 2400
        mDensity = densityDpi;

        Log.d(TAG," >>> Creating display metric w: " + mWidth + " h: " + mHeight + " dens: " + mDensity);

        mImageReader = ImageReader.newInstance(mWidth, mHeight, PixelFormat.RGBA_8888, MAX_IMAGES);
        mVirtualDisplay = mMediaProjection.createVirtualDisplay(SCREENCAP_NAME, mWidth, mHeight,
                mDensity, getVirtualDisplayFlags(), mImageReader.getSurface(), null, mHandler);
        mImageReader.setOnImageAvailableListener(new ImageAvailableListener(), mHandler);

        mCallback.onReceivedDisplayInfo(mWidth, mHeight);

    }

并且在 OnimageAvailable 上接收到 rgba 原始字节:

 private class ImageAvailableListener implements ImageReader.OnImageAvailableListener {
        @Override
        public void onImageAvailable(ImageReader reader) {

            try (Image image = mImageReader.acquireLatestImage()) {
                if (image != null) {
                    publishFrame(image);
                }

            } catch (Exception e) {
                e.printStackTrace();
                mCallback.onError(e.getMessage());
            }
        }
    }
private void publishFrame(Image image) {

        int mWidth = image.getWidth(); 
        int mHeight = image.getHeight(); 

        // Four bytes per pixel: width * height * 4.
        byte[] rgbaBytes = new byte[mWidth * mHeight * 4];
        // put the data into the rgbaBytes array.
        image.getPlanes()[0].getBuffer().get(rgbaBytes);

        image.close();

        if (mCallback != null) {
            mCallback.onScreenFrameCaptured(rgbaBytes);
        }
    }

到目前为止,一切都很好,并且框架可以毫无问题地渲染到表面视图上。但事情在这一点上变得有趣:

在此处输入图像描述

将宽高改为640 x 480后,效果好一点:

在此处输入图像描述

但如您所见,共享屏幕的纵横比有问题。最后,当我将宽度和高度更改为 768 * 1366 时,结果在某种程度上可以接受但

在此处输入图像描述

  1. 为什么当我为 Imageريالeader 和 VirtualDisplay 设置设备屏幕的宽度和高度时,共享屏幕损坏了?(对于这个设备:宽度=1080 高度=2400)

  2. 为什么当我设置高度大于宽度时,共享屏幕是好的?

  3. 在上一张图中,共享屏幕并没有覆盖整个目标 SurfaceView。如何为 VirtualDisplay 和 ImageReader 设置覆盖整个 SurfaceView 的分辨率?

4

0 回答 0