Try to start streaming screen capture.
This commit is contained in:
parent
8eaa2f8dfb
commit
7939ecaedc
|
@ -24,6 +24,7 @@ import android.content.Intent
|
||||||
import android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP
|
import android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
|
import android.media.projection.MediaProjection
|
||||||
import android.media.projection.MediaProjectionManager
|
import android.media.projection.MediaProjectionManager
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
@ -32,6 +33,7 @@ import android.util.Rational
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
|
import androidx.activity.result.ActivityResult
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
|
@ -76,6 +78,7 @@ import org.matrix.android.sdk.api.session.call.TurnServerResponse
|
||||||
import org.matrix.android.sdk.api.session.room.model.call.EndCallReason
|
import org.matrix.android.sdk.api.session.room.model.call.EndCallReason
|
||||||
import org.webrtc.EglBase
|
import org.webrtc.EglBase
|
||||||
import org.webrtc.RendererCommon
|
import org.webrtc.RendererCommon
|
||||||
|
import org.webrtc.ScreenCapturerAndroid
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -636,16 +639,34 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
|
||||||
|
|
||||||
private val screenSharingPermissionActivityResultLauncher = registerStartForActivityResult { activityResult ->
|
private val screenSharingPermissionActivityResultLauncher = registerStartForActivityResult { activityResult ->
|
||||||
if (activityResult.resultCode == Activity.RESULT_OK) {
|
if (activityResult.resultCode == Activity.RESULT_OK) {
|
||||||
callViewModel.handle(VectorCallViewActions.StartScreenSharing)
|
|
||||||
// We need to start a foreground service with a sticky notification during screen sharing
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
// We need to start a foreground service with a sticky notification during screen sharing
|
||||||
|
startScreenSharingService(activityResult)
|
||||||
|
} else {
|
||||||
|
startScreenSharing(activityResult)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startScreenSharing(activityResult: ActivityResult) {
|
||||||
|
val videoCapturer = ScreenCapturerAndroid(activityResult.data, object : MediaProjection.Callback() {
|
||||||
|
override fun onStop() {
|
||||||
|
Timber.v("User revoked the screen capturing permission")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
callViewModel.handle(VectorCallViewActions.StartScreenSharing(videoCapturer))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startScreenSharingService(activityResult: ActivityResult) {
|
||||||
ContextCompat.startForegroundService(
|
ContextCompat.startForegroundService(
|
||||||
this,
|
this,
|
||||||
Intent(this, ScreenCaptureService::class.java)
|
Intent(this, ScreenCaptureService::class.java)
|
||||||
)
|
)
|
||||||
screenCaptureServiceConnection.bind()
|
screenCaptureServiceConnection.bind(object : ScreenCaptureServiceConnection.Callback {
|
||||||
}
|
override fun onServiceConnected() {
|
||||||
|
startScreenSharingService(activityResult)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleShowScreenSharingPermissionDialog() {
|
private fun handleShowScreenSharingPermissionDialog() {
|
||||||
|
|
|
@ -19,6 +19,7 @@ package im.vector.app.features.call
|
||||||
import im.vector.app.core.platform.VectorViewModelAction
|
import im.vector.app.core.platform.VectorViewModelAction
|
||||||
import im.vector.app.features.call.audio.CallAudioManager
|
import im.vector.app.features.call.audio.CallAudioManager
|
||||||
import im.vector.app.features.call.transfer.CallTransferResult
|
import im.vector.app.features.call.transfer.CallTransferResult
|
||||||
|
import org.webrtc.VideoCapturer
|
||||||
|
|
||||||
sealed class VectorCallViewActions : VectorViewModelAction {
|
sealed class VectorCallViewActions : VectorViewModelAction {
|
||||||
object EndCall : VectorCallViewActions()
|
object EndCall : VectorCallViewActions()
|
||||||
|
@ -41,5 +42,5 @@ sealed class VectorCallViewActions : VectorViewModelAction {
|
||||||
data class CallTransferSelectionResult(val callTransferResult: CallTransferResult) : VectorCallViewActions()
|
data class CallTransferSelectionResult(val callTransferResult: CallTransferResult) : VectorCallViewActions()
|
||||||
object TransferCall : VectorCallViewActions()
|
object TransferCall : VectorCallViewActions()
|
||||||
object ToggleScreenSharing : VectorCallViewActions()
|
object ToggleScreenSharing : VectorCallViewActions()
|
||||||
object StartScreenSharing : VectorCallViewActions()
|
data class StartScreenSharing(val videoCapturer: VideoCapturer) : VectorCallViewActions()
|
||||||
}
|
}
|
||||||
|
|
|
@ -348,7 +348,7 @@ class VectorCallViewModel @AssistedInject constructor(
|
||||||
handleToggleScreenSharing(state.isSharingScreen)
|
handleToggleScreenSharing(state.isSharingScreen)
|
||||||
}
|
}
|
||||||
is VectorCallViewActions.StartScreenSharing -> {
|
is VectorCallViewActions.StartScreenSharing -> {
|
||||||
call?.startSharingScreen()
|
call?.startSharingScreen(action.videoCapturer)
|
||||||
setState {
|
setState {
|
||||||
copy(isSharingScreen = true)
|
copy(isSharingScreen = true)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,17 @@ class ScreenCaptureServiceConnection @Inject constructor(
|
||||||
private val context: Context
|
private val context: Context
|
||||||
) : ServiceConnection {
|
) : ServiceConnection {
|
||||||
|
|
||||||
|
interface Callback {
|
||||||
|
fun onServiceConnected()
|
||||||
|
}
|
||||||
|
|
||||||
private var isBound = false
|
private var isBound = false
|
||||||
private var screenCaptureService: ScreenCaptureService? = null
|
private var screenCaptureService: ScreenCaptureService? = null
|
||||||
|
private var callback: Callback? = null
|
||||||
|
|
||||||
|
fun bind(callback: Callback) {
|
||||||
|
this.callback = callback
|
||||||
|
|
||||||
fun bind() {
|
|
||||||
if (!isBound) {
|
if (!isBound) {
|
||||||
Intent(context, ScreenCaptureService::class.java).also { intent ->
|
Intent(context, ScreenCaptureService::class.java).also { intent ->
|
||||||
context.bindService(intent, this, 0)
|
context.bindService(intent, this, 0)
|
||||||
|
@ -45,6 +52,7 @@ class ScreenCaptureServiceConnection @Inject constructor(
|
||||||
override fun onServiceConnected(className: ComponentName, binder: IBinder) {
|
override fun onServiceConnected(className: ComponentName, binder: IBinder) {
|
||||||
screenCaptureService = (binder as ScreenCaptureService.LocalBinder).getService()
|
screenCaptureService = (binder as ScreenCaptureService.LocalBinder).getService()
|
||||||
isBound = true
|
isBound = true
|
||||||
|
callback?.onServiceConnected()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onServiceDisconnected(className: ComponentName) {
|
override fun onServiceDisconnected(className: ComponentName) {
|
||||||
|
|
|
@ -84,6 +84,7 @@ import org.webrtc.RtpTransceiver
|
||||||
import org.webrtc.SessionDescription
|
import org.webrtc.SessionDescription
|
||||||
import org.webrtc.SurfaceTextureHelper
|
import org.webrtc.SurfaceTextureHelper
|
||||||
import org.webrtc.SurfaceViewRenderer
|
import org.webrtc.SurfaceViewRenderer
|
||||||
|
import org.webrtc.VideoCapturer
|
||||||
import org.webrtc.VideoSource
|
import org.webrtc.VideoSource
|
||||||
import org.webrtc.VideoTrack
|
import org.webrtc.VideoTrack
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
@ -770,8 +771,27 @@ class WebRtcCall(
|
||||||
return currentCaptureFormat
|
return currentCaptureFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startSharingScreen() {
|
fun startSharingScreen(videoCapturer: VideoCapturer) {
|
||||||
// TODO. Will be handled within the next PR.
|
val factory = peerConnectionFactoryProvider.get() ?: return
|
||||||
|
val videoSource = factory.createVideoSource(true)
|
||||||
|
val audioSource = factory.createAudioSource(DEFAULT_AUDIO_CONSTRAINTS)
|
||||||
|
val surfaceTextureHelper = SurfaceTextureHelper.create("CaptureThread", rootEglBase!!.eglBaseContext)
|
||||||
|
videoCapturer.initialize(surfaceTextureHelper, context, videoSource.capturerObserver)
|
||||||
|
videoCapturer.startCapture(currentCaptureFormat.width, currentCaptureFormat.height, currentCaptureFormat.fps)
|
||||||
|
|
||||||
|
val videoTrack = factory.createVideoTrack("ARDAMSv0", videoSource).apply { setEnabled(true) }
|
||||||
|
val audioTrack = factory.createAudioTrack("ARDAMSa0", audioSource).apply { setEnabled(true) }
|
||||||
|
|
||||||
|
val localMediaStream = factory.createLocalMediaStream("ARDAMS")
|
||||||
|
peerConnection?.addTrack(videoTrack)
|
||||||
|
peerConnection?.addTrack(audioTrack)
|
||||||
|
localMediaStream.addTrack(videoTrack)
|
||||||
|
localMediaStream.addTrack(audioTrack)
|
||||||
|
|
||||||
|
localAudioSource = audioSource
|
||||||
|
localVideoSource = videoSource
|
||||||
|
localAudioTrack = audioTrack
|
||||||
|
localVideoTrack = videoTrack
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stopSharingScreen() {
|
fun stopSharingScreen() {
|
||||||
|
|
Loading…
Reference in New Issue