Я пытаюсь реализовать Screen Share с помощью Agora.io на Android. Я попытался проследить за их демонстрацией, однако решение, использующее низкоуровневый графический API Android, кажется слишком сложным, поэтому я попытался использовать для этого 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 или мне нужно спуститься ниже, чтобы начать использовать EglCore и т. Д. Из демонстрационной реализации Agora?
Я могу проверить, что вызывается OnImageAvailable (несколько раз, пока я его не остановлю) PushExternalVideoFrame возвращает «true», что выглядит так, как будто кадры были успешно отправлены.
Однако это не дает никаких результатов, я не вижу, что экран используется совместно. Так что я бы хотя бы убедился, что это возможное решение.