Reputation: 1
I'm trying to implement screen sharing functionality using the .NET MAUI Blazor framework. I created a ScreenshareService to handle the screen sharing process. However, when I attempt to call the other person and initiate screen sharing, they can only see a black screen along with the message: "Abc user is sharing now." The shared display is not being transmitted correctly.
Details:
Framework Used: .NET MAUI Blazor Service Created: ScreenshareService Issue: Opposite person sees a black screen instead of the shared display Message Displayed: "Abc user is sharing now" I would appreciate any guidance or suggestions on how to resolve this issue. Thank you!
{
private const int ScreenCaptureRequestCode = 1001;
private readonly TaskCompletionSource<bool> _taskCompletionSource = new TaskCompletionSource<bool>();
private readonly MediaProjectionManager _mediaProjectionManager;
private MediaProjection _mediaProjection;
private VirtualDisplay _virtualDisplay;
private Surface _surface;
private readonly Context _context;
private readonly SignalingService _signalingService;
private readonly IMessengerService _messengerService;
private MediaCodec mediaCodec;
private WebRTCVideoTrack _webRTCVideoTrack;
private IVideoTrack _videoTrack;
public string _roomId;
public ScreenShareService(SignalingService signalingService, IMessengerService messengerService)
{
_signalingService = signalingService ?? throw new ArgumentNullException(nameof(signalingService));
_messengerService = messengerService ?? throw new ArgumentNullException(nameof(messengerService));
_context = MainActivity.Instance ?? throw new ArgumentNullException(nameof(MainActivity.Instance));
_mediaProjectionManager = (MediaProjectionManager)_context.GetSystemService(Context.MediaProjectionService);
_videoTrack = new WebRTCVideoTrack();
Console.WriteLine("ScreenShareService initialized.");
}
public Task<bool> StartScreenShareAsync()
{
Intent captureIntent = _mediaProjectionManager.CreateScreenCaptureIntent();
if (_context is Activity activity)
{
var intent = new Intent(_context, typeof(ScreenCaptureForegroundService));
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
_context.StartForegroundService(intent);
}
else
{
_context.StartService(intent);
}
_roomId = _messengerService.RoomId.ToString();
Console.WriteLine($"Starting screen share for Room ID: {_roomId}");
activity.StartActivityForResult(captureIntent, ScreenCaptureRequestCode);
}
else
{
Console.WriteLine("Context is not an Activity. Cannot start screen share.");
_taskCompletionSource.SetResult(false);
}
return _taskCompletionSource.Task;
}
public async Task StopScreenShareAsync()
{
try
{
_virtualDisplay?.Release();
_mediaProjection?.Stop();
_mediaProjection = null;
_virtualDisplay = null;
_surface?.Release();
_surface = null;
Console.WriteLine("Releasing VirtualDisplay and MediaProjection.");
await _signalingService.NotifyScreenShareStateChangeAsync(_roomId, false);
Console.WriteLine("Screen sharing stopped.");
var intent = new Intent(_context, typeof(ScreenCaptureForegroundService));
_context.StopService(intent);
Console.WriteLine("Foreground service stopped.");
}
catch (Exception ex)
{
Console.WriteLine($"Error stopping screen share: {ex.Message}");
}
}
public void HandleActivityResult(int requestCode, Result resultCode, Intent data, string roomId)
{
Console.WriteLine($"HandleActivityResult called with requestCode: {requestCode}, resultCode: {resultCode}");
if (requestCode == ScreenCaptureRequestCode)
{
if (resultCode == Result.Ok)
{
_mediaProjection = _mediaProjectionManager.GetMediaProjection((int)resultCode, data);
if (_mediaProjection != null)
{
_roomId = roomId;
Console.WriteLine($"MediaProjection obtained for Room ID: {_roomId}");
SetupVirtualDisplay();
_taskCompletionSource.SetResult(true);
_ = _signalingService.NotifyScreenShareStateChangeAsync(roomId, true);
Console.WriteLine("Screen sharing started.");
}
else
{
_taskCompletionSource.SetResult(false);
Console.WriteLine("Failed to obtain MediaProjection.");
}
}
else
{
_taskCompletionSource.SetResult(false);
Console.WriteLine("User denied screen sharing permission.");
}
}
}
private void SetupVirtualDisplay()
{
var metrics = _context.Resources.DisplayMetrics;
int screenWidth = metrics.WidthPixels;
int screenHeight = metrics.HeightPixels;
int density = (int)metrics.DensityDpi;
Console.WriteLine($"Setting up VirtualDisplay: {screenWidth}x{screenHeight} at density {density}");
_surface = GetSurface(screenWidth, screenHeight);
_virtualDisplay = _mediaProjection.CreateVirtualDisplay(
"ScreenShare",
screenWidth,
screenHeight,
density,
DisplayFlags.Presentation,
_surface,
null,
null
);
Console.WriteLine("VirtualDisplay created successfully.");
Task.Run(() => StartEncodingAsync());
}
private Surface GetSurface(int width, int height)
{
var mediaCodec = MediaCodec.CreateEncoderByType(MediaFormat.MimetypeVideoAvc);
var format = MediaFormat.CreateVideoFormat(MediaFormat.MimetypeVideoAvc, width, height);
format.SetInteger(MediaFormat.KeyColorFormat, 2130708361);
format.SetInteger(MediaFormat.KeyBitRate, 2500000);
format.SetInteger(MediaFormat.KeyFrameRate, 30);
format.SetInteger(MediaFormat.KeyIFrameInterval, 5);
mediaCodec.Configure(format, null, null, MediaCodecConfigFlags.Encode);
var inputSurface = mediaCodec.CreateInputSurface();
mediaCodec.Start();
Console.WriteLine("MediaCodec configured and input surface created.");
return inputSurface;
}
private async Task StartEncodingAsync()
{
var bufferInfo = new MediaCodec.BufferInfo();
while (true)
{
int outputBufferIndex = mediaCodec.DequeueOutputBuffer(bufferInfo, 10000);
if (outputBufferIndex >= 0)
{
ByteBuffer outputBuffer = mediaCodec.GetOutputBuffer(outputBufferIndex);
byte[] encodedData = new byte[bufferInfo.Size];
outputBuffer.Get(encodedData);
outputBuffer.Clear();
if (_videoTrack != null)
{
await _videoTrack.WriteEncodedFrameAsync(encodedData);
Console.WriteLine($"Sent encoded frame of size: {encodedData.Length}");
}
else
{
Console.WriteLine("WebRTCVideoTrack is not initialized. Encoded frame not sent.");
}
mediaCodec.ReleaseOutputBuffer(outputBufferIndex, false);
}
else if (outputBufferIndex == -3)
{
Console.WriteLine("Output buffers changed. Adjusting...");
}
else if (outputBufferIndex == -2)
{
var newFormat = mediaCodec.OutputFormat;
Console.WriteLine($"Output format changed: {newFormat}");
}
else if (outputBufferIndex == -1)
{
await Task.Delay(10);
Console.WriteLine("No output buffer available, retrying...");
}
else
{
Console.WriteLine($"Unhandled outputBufferIndex: {outputBufferIndex}");
}
}
}
}[enter image description here][1]
Web socket
---------------
_socket.On("remote-screen-share-state-change", response =>
{
var data = response.GetValue<JsonElement>();
string userId = data.GetProperty("userId").GetString();
bool isScreenSharing = data.GetProperty("isScreenSharing").GetBoolean();
RemoteScreenShareStateChanged?.Invoke(this, (userId, isScreenSharing));
});
public async Task NotifyScreenShareStateChangeAsync(string roomId, bool isScreenSharing)
{
await _socket.EmitAsync("screen-share-state-change", new { roomId, isScreenSharing });
Console.WriteLine($"Room {roomId}: Screen sharing {(isScreenSharing ? "started" : "stopped")}.");
await Task.CompletedTask;
}````
[1]: https://i.sstatic.net/H3xb0mOy.jpg
Upvotes: 0
Views: 50