Android-从Surface/virtualDisplay获取字节[]

Android-从Surface/virtualDisplay获取字节[],android,webrtc,surface,android-mediaprojection,Android,Webrtc,Surface,Android Mediaprojection,我正在尝试使用projectionapi和Webrtc将我的android设备屏幕投射到web浏览器上 投影API将其输出渲染到曲面并返回虚拟显示。我一直干到现在。我看到了android的webrtc库。他们已经做到只接收设备摄像头的输入。我正在尝试读取和修改webrtc代码,以流式传输显示在表面上的任何内容 我的问题是,如何像摄像头.PreviewCallback功能一样定期从曲面接收字节[]数据。我还有什么其他选择?以下是我解决问题的方法。我使用ImageReader类,比如 imageRe

我正在尝试使用
projectionapi
Webrtc
将我的android设备屏幕投射到web浏览器上

投影API
将其输出渲染到
曲面
并返回虚拟显示。我一直干到现在。我看到了android的webrtc库。他们已经做到只接收设备摄像头的输入。我正在尝试读取和修改webrtc代码,以流式传输显示在表面上的任何内容


我的问题是,如何像
摄像头.PreviewCallback
功能一样定期从
曲面
接收字节[]数据。我还有什么其他选择?

以下是我解决问题的方法。我使用ImageReader类,比如

imageReader = ImageReader.newInstance(displayWidth, displayHeight, PixelFormat.RGBA_8888, 2);
mediaProjection.createVirtualDisplay("screencapture",
                    displayWidth, displayHeight, density,
                    flags, imageReader.getSurface(), null, handler);
imageReader.setOnImageAvailableListener(new ImageAvailableListener(), null);


private class ImageAvailableListener implements ImageReader.OnImageAvailableListener {
    @Override
    public void onImageAvailable(ImageReader reader) {
        Image image = null;
        Bitmap bitmap = null;

        ByteArrayOutputStream stream = null;

        try {
            image = imageReader.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 * displayWidth;

                // create bitmap
                bitmap = Bitmap.createBitmap(displayWidth + rowPadding / pixelStride,
                        displayHeight, Bitmap.Config.ARGB_8888);
                bitmap.copyPixelsFromBuffer(buffer);
                    stream = new ByteArrayOutputStream();
                    bitmap.compress(Bitmap.CompressFormat.JPEG, 50, stream);
                    StringBuilder sb = new StringBuilder();
                    sb.append("data:image/png;base64,");
                    sb.append(StringUtils.newStringUtf8(Base64.encode(stream.toByteArray(), Base64.DEFAULT)));
                WebrtcClient.sendProjection(sb.toString());
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

我正在将字节[]转换为Base64字符串,并通过webrtc数据通道发送到。

如果帧很小,您可以将它们全部传递。如果它们很少出现,您可以将它们转换为JPEG或PNG格式。如果您想要接近显示刷新率,则需要使用视频编码器将其转换为视频流。对于stackoverflow,您的问题有点含糊不清——本网站专门针对特定的编程问题。@fadden您可以看看这个问题吗:我只需要您回答是或否。@fadden我已经更新了这个问题。请提供您的意见。如果我想的方向不对。请告诉我正确的方向。理论上,您可以使用ImageReader曲面(),但我不知道它是否适用于RGB888曲面(用于相机YUV输出)。您可能需要在SurfaceTexture曲面上接收帧,将它们渲染到pbuffer,然后使用
glReadPixels()
提取它们。是否需要
字节[]
?根据您试图执行的操作,可能有一种方法可以让GPU执行。锯齿像素通常是忽略步幅的结果——请确保您使用的是
getPixelStride()
getRowStride()
。ImageReader是使用CPU访问表面内容的最快、最简单的方法。另一种方法是执行以下操作:将视频发送到SurfaceTexture,渲染视频,并使用
glReadPixels()
提取像素。在这种情况下,ImageReader的FPS性能如何?你为什么选择通过数据通道而不是常规视频通道发送流?@MichaelP ImageReader的性能相当好。如果您不希望处理surfaceTexture,那么ImageReader是从surface获取字节[]的最快方法。我在这个项目中使用了webrtc android sdk。他们对视频频道进行了编码,以便与设备摄像机配合使用。我试图通过编辑他们的源代码来改变这种行为,但收效甚微。上述解决方案对我来说非常有效。@Shubenda,谢谢你的回复。我实际上也在尝试做同样的事情,今天我花了一整天的时间,试图找出如何修改他们的代码来做到这一点。这是我的新问题,它们确实与java包装器和C++实现紧密结合。您提到了SurfaceTexture,我不认为SurfaceTexture可以为您提供输入曲面(或获取曲面),因此似乎唯一的解决方案是使用ImageReader。我只是想确保它没有调用glReadPixels那么慢,而且它可以运行30次FPS@shubendrak:我完全在同一条船上,但没有使用数据通道。你能帮我看一下代码吗?你能帮我看一下用于捕获屏幕的库吗?以及有关接收Base64流的webRTC库的信息。