Alavu _alu
Alavu _alu

Reputation: 1

.NET MAUI Blazor Android screen sharing is showing a black screen

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

Answers (0)

Related Questions