Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Screen sharing over WebRTC #5911

Merged
merged 12 commits into from
May 10, 2022
Merged

Screen sharing over WebRTC #5911

merged 12 commits into from
May 10, 2022

Conversation

onurays
Copy link
Contributor

@onurays onurays commented May 3, 2022

screen_sharing_pr

  1. Start a video call between 2 or more devices
  2. Once the call is connected tap the menu icon (...)
  3. You should see the "Start sharing screen" option, select it
  4. A system permission dialog should appear, accept it
  5. Your screen will be streamed to other devices (in ~5 seconds)
  6. A sticky push notification should appear for Android 10 or later versions
  7. "Start sharing screen" button should turn to "Stop sharing screen"

@onurays onurays requested review from a team, ericdecanini and mnaturel and removed request for a team May 3, 2022 12:17
private fun startScreenSharing(activityResult: ActivityResult) {
val videoCapturer = ScreenCapturerAndroid(activityResult.data, object : MediaProjection.Callback() {
override fun onStop() {
Timber.v("User revoked the screen capturing permission")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're keeping this in production I would make this Timber.i

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Yes, we have to implement this dummy callback.

Comment on lines 779 to 802
val factory = peerConnectionFactoryProvider.get() ?: return

this.videoCapturer = videoCapturer

val localMediaStream = factory.createLocalMediaStream(STREAM_ID)
val videoSource = factory.createVideoSource(videoCapturer.isScreencast)

// Start capturing screen
val surfaceTextureHelper = SurfaceTextureHelper.create("CaptureThread", rootEglBase!!.eglBaseContext)
videoCapturer.initialize(surfaceTextureHelper, context, videoSource.capturerObserver)
videoCapturer.startCapture(currentCaptureFormat.width, currentCaptureFormat.height, currentCaptureFormat.fps)

// Remove local camera previews
localSurfaceRenderers.forEach { it.get()?.let { localVideoTrack?.removeSink(it) } }

// Show screen preview locally
localVideoTrack = factory.createVideoTrack(VIDEO_TRACK_ID, videoSource).apply { setEnabled(true) }
localMediaStream?.addTrack(localVideoTrack)
localSurfaceRenderers.forEach { it.get()?.let { localVideoTrack?.addSink(it) } }

// Remove camera stream
peerConnection?.removeTrack(videoSender)

screenSender = peerConnection?.addTrack(localVideoTrack, listOf(STREAM_ID))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each of these "regions" (as separated by the comments) can be made more readable by each being their own private function. This method can then read like a story without any comments

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. This class needs refactoring.

@github-actions
Copy link

github-actions bot commented May 3, 2022

Unit Test Results

122 files  ±0  122 suites  ±0   2m 9s ⏱️ +3s
205 tests ±0  205 ✔️ ±0  0 💤 ±0  0 ±0 
690 runs  ±0  690 ✔️ ±0  0 💤 ±0  0 ±0 

Results for commit bb862cc. ± Comparison against base commit 0325754.

♻️ This comment has been updated with latest results.

@onurays onurays requested a review from ericdecanini May 3, 2022 14:18
Copy link
Contributor

@mnaturel mnaturel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When testing on a real device (Nokia 7.2, Android 11), it seems the sharing is not working. I click on share screen then I see a dialog saying I will share all the content of my screen. And then I see a notification saying a screen sharing is running. But the sharing option stays with "Share my screen" and not "Stop sharing" like I would expect. And I don't see the share on Web. It seems like it does not transfer the video stream.

Also, could you please add a bit more of context and explanation in the PR description (for example how to test, to see what is expected).

@@ -147,6 +147,7 @@ class VectorCallViewModel @AssistedInject constructor(
setState { copy(otherKnownCallInfo = null) }
}
}
_viewEvents.post(VectorCallViewEvents.StopScreenSharingService)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I think the set of the isSharingScreen to false in the state is missing. Maybe we should reuse an mutualize what is done in handleToggleScreenSharing() when screen is shared:

if (isSharingScreen) {
    call?.stopSharingScreen()
    setState {
        copy(isSharingScreen = false)
    }
    _viewEvents.post(VectorCallViewEvents.StopScreenSharingService)
}

What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, although we finish the call activity as soon as the call ended.

private var callback: Callback? = null

fun bind(callback: Callback) {
this.callback = callback
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to reset the callback to null when unbound to the service in onServiceDisconnected for example.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, done.

@@ -770,12 +775,49 @@ class WebRtcCall(
return currentCaptureFormat
}

fun startSharingScreen() {
// TODO. Will be handled within the next PR.
fun startSharingScreen(videoCapturer: VideoCapturer) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tried to extract the screen sharing capabilities into a dedicated component to avoid adding new responsabilities to WebRtcCall?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it is easily possible. This class has many local fields. We will start implementing Element Call soon, so we probably won't invest in this class more.

@onurays onurays requested a review from mnaturel May 4, 2022 12:30
@onurays
Copy link
Contributor Author

onurays commented May 4, 2022

When testing on a real device (Nokia 7.2, Android 11), it seems the sharing is not working. I click on share screen then I see a dialog saying I will share all the content of my screen. And then I see a notification saying a screen sharing is running. But the sharing option stays with "Share my screen" and not "Stop sharing" like I would expect. And I don't see the share on Web. It seems like it does not transfer the video stream.

Also, could you please add a bit more of context and explanation in the PR description (for example how to test, to see what is expected).

Thank you for testing by turning off the camera :) I will fix this.

@mnaturel
Copy link
Contributor

mnaturel commented May 9, 2022

I tested again with physical device (Android 11, Nokia 7.2), here is what I discovered:

  • in audio call, when I approach my fingers from the front camera or status bar, the screen becomes black (I guess it behaves like this is several devices since you are supposed to talk to the phone). It may be annoying when screen sharing is running, don't know if we can do something about it.
  • in audio call, after stopping a screen sharing, the last image stays in the call preview in the web. I don't know if the problem comes from our side. It does not occur in a video call (even if we disable the video after the video call has started)

@onurays
Copy link
Contributor Author

onurays commented May 9, 2022

I tested again with physical device (Android 11, Nokia 7.2), here is what I discovered:

  • in audio call, when I approach my fingers from the front camera or status bar, the screen becomes black (I guess it behaves like this is several devices since you are supposed to talk to the phone). It may be annoying when screen sharing is running, don't know if we can do something about it.
  • in audio call, after stopping a screen sharing, the last image stays in the call preview in the web. I don't know if the problem comes from our side. It does not occur in a video call (even if we disable the video after the video call has started)

Proximity sensor issue is a good catch and fixed. Second one seems the responsibility of web, because we stop sending streams.

@mnaturel
Copy link
Contributor

mnaturel commented May 9, 2022

Thanks for fixing the proximity sensor issue, it is okay now. I discovered a new thing:

  • in a video call, I start sharing screen. When I disabled the video it disable the screen sharing as well. I think the user expects to only turn off the camera and not both camera and screen sharing.

@onurays onurays removed the request for review from ericdecanini May 10, 2022 09:50
@onurays onurays merged commit 185cd31 into develop May 10, 2022
@onurays onurays deleted the feature/ons/voip_screen_sharing branch May 10, 2022 10:06
@github-actions
Copy link

Matrix SDK

Integration Tests Results:

  • [org.matrix.android.sdk.session]
    = passed=15 failures=5 errors=0 skipped=3
  • [org.matrix.android.sdk.account]
    = passed=3 failures=0 errors=0 skipped=2
  • [org.matrix.android.sdk.internal]
    = passed=110 failures=0 errors=0 skipped=38
  • [org.matrix.android.sdk.ordering]
    = passed=16 failures=0 errors=0 skipped=0
  • [org.matrix.android.sdk.PermalinkParserTest]
    = passed=2 failures=0 errors=0 skipped=0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants