Android-使用Agora.io进行屏幕共享

时间:2020-05-19 12:45:25

标签: android agora.io screensharing

我正在尝试在Android上使用 Agora.io 实施屏幕共享。我尝试遵循他们的演示,但是使用低级Android图形API的解决方案似乎太复杂了,因此我尝试使用ImageReader。

根据我的活动创建一个服务( ShareScreenService 从服务继承)

要在此处开始屏幕共享

private void StartScreenShare(int resultCode, Intent resultData)
        {
            var mediaProjectionManager = (MediaProjectionManager)GetSystemService(MediaProjectionService);
            var mediaProjection = mediaProjectionManager.GetMediaProjection(resultCode, resultData);
            _shareScreenImageAvailableListener = new ShareScreenImageAvailableListener(this);
            var virtualDisplay = mediaProjection.CreateVirtualDisplay("sharescreen", Resources.DisplayMetrics.WidthPixels, Resources.DisplayMetrics.HeightPixels, (int)Resources.DisplayMetrics.DensityDpi, DisplayFlags.SupportsProtectedBuffers | DisplayFlags.Presentation, _shareScreenImageAvailableListener.Surface, null, _handler);
            var mediaProjectionCallback = new MediaProjectionCallback(virtualDisplay);
            mediaProjection.RegisterCallback(mediaProjectionCallback, _handler);

            AgoraVideoService.Instance.StartScreenShare();
        }

AgoraVideoService.Instance.StartScreenShare does following:

internal void StartScreenShare()
        {
            _agoraEngine.SetExternalVideoSource(true, false, true);
        }

我的 ShareScreenImageAvailableListener 看起来像这样:

public class ShareScreenImageAvailableListener : Java.Lang.Object, ImageReader.IOnImageAvailableListener
    {
        private ScreenShareService _screenShareService;
        private ImageReader _imageReader;

        public Surface Surface
        {
            get
            {
                return _imageReader.Surface;
            }
        }

        public ShareScreenImageAvailableListener(ScreenShareService screenShareService)
        {
            _screenShareService = screenShareService;
            _imageReader = ImageReader.NewInstance(_screenShareService.Width, _screenShareService.Height, Android.Graphics.ImageFormatType.Jpeg, 1);
            _imageReader.SetOnImageAvailableListener(this, _screenShareService.Handler);
        }

        public void OnImageAvailable(ImageReader reader)
        {
            using (var image = reader.AcquireLatestImage())
            {
                using (var planes = image.GetPlanes()[0])
                {
                    using (var buffer = planes.Buffer)
                    {
                        byte[] bytes = new byte[buffer.Capacity()];
                        buffer.Get(bytes);

                        _screenShareService.ShareScreenImage(bytes, image.Height, image.Format, planes.PixelStride);
                    }
                }
                image.Close();
            }
        }
    }

然后在共享 ShareScreenImage 时:

internal void ShareScreenImage(byte[] bytes, int height, ImageFormatType format, int pixelStride)
        {
            var agoraVideoFrame = new AgoraVideoFrame()
            {
                Buf = bytes,
                Height = height,
                Format = (int)format,
                Stride = pixelStride,
                TimeStamp = DateTime.UtcNow.Ticks,
               CropBottom = 0,
               CropLeft = 0,
               CropRight = 0,
               CropTop = 0
            };

            AgoraVideoService.Instance.ShareExternalVideoFrame(agoraVideoFrame);
        }

最后是 ShareExternalVideoFrame ,如下所示:

_agoraEngine.PushExternalVideoFrame(agoraVideoFrame);

最后,我的问题是:我的想法在实现这一点上是否正确?我可以使用ImageReader还是需要降低以从Agora演示实现中开始使用EglCore等?

我可以验证是否已调用OnImageAvailable(多次,直到停止为止)。 PushExternalVideoFrame 返回“ true”,看起来像帧已成功推送

但是这不会产生任何结果,我看不到共享的屏幕。因此,我至少会验证这是一个可行的解决方案。

1 个答案:

答案 0 :(得分:1)

使用EglCore更为安全,因为尚未使用ImageReader对Agora进行测试。您可以使用高级指南和示例应用程序来了解如何将其与EglCore一起使用。

以下是示例应用程序的链接:https://github.com/AgoraIO/Advanced-Video

这是指南的链接:https://docs.agora.io/en/Video/custom_video_android?platform=Android