feat: setting up rotation for the remote render view
This commit is contained in:
parent
eb2e3d075e
commit
a11a5da7c2
|
@ -44,6 +44,8 @@ import org.thoughtcrime.securesms.webrtc.CallViewModel.State.CALL_PRE_INIT
|
|||
import org.thoughtcrime.securesms.webrtc.CallViewModel.State.CALL_RINGING
|
||||
import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager.AudioDevice.EARPIECE
|
||||
import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager.AudioDevice.SPEAKER_PHONE
|
||||
import org.thoughtcrime.securesms.webrtc.data.quadrantRotation
|
||||
import org.thoughtcrime.securesms.webrtc.video.RotationVideoProcessor
|
||||
|
||||
@AndroidEntryPoint
|
||||
class WebRtcCallActivity : PassphraseRequiredActionBarActivity() {
|
||||
|
@ -73,7 +75,7 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() {
|
|||
private val rotationListener by lazy {
|
||||
object : OrientationEventListener(this) {
|
||||
override fun onOrientationChanged(orientation: Int) {
|
||||
viewModel.setDeviceRotation(orientation)
|
||||
viewModel.deviceRotation = orientation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package org.thoughtcrime.securesms.webrtc
|
|||
|
||||
import android.content.Context
|
||||
import android.telephony.TelephonyManager
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.LayoutParams.*
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.serialization.Serializable
|
||||
|
@ -182,10 +184,12 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va
|
|||
eglBase = base
|
||||
localRenderer = SurfaceViewRenderer(context).apply {
|
||||
setEnableHardwareScaler(true)
|
||||
setScalingType(SCALE_ASPECT_FIT)
|
||||
}
|
||||
|
||||
remoteRenderer = SurfaceViewRenderer(context).apply {
|
||||
setEnableHardwareScaler(true)
|
||||
setScalingType(SCALE_ASPECT_FIT)
|
||||
}
|
||||
|
||||
localRenderer?.init(base.eglBaseContext, null)
|
||||
|
@ -198,7 +202,6 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va
|
|||
Log.d("Loki", "remote rotation: $p2")
|
||||
}
|
||||
})
|
||||
remoteRenderer?.setScalingType(SCALE_ASPECT_FIT)
|
||||
|
||||
val encoderFactory = DefaultVideoEncoderFactory(base.eglBaseContext, true, true)
|
||||
val decoderFactory = DefaultVideoDecoderFactory(base.eglBaseContext)
|
||||
|
|
|
@ -66,9 +66,11 @@ class CallViewModel @Inject constructor(private val callManager: CallManager): V
|
|||
val remoteVideoEnabledState
|
||||
get() = callManager.remoteVideoEvents.map { it.isEnabled }
|
||||
|
||||
fun setDeviceRotation(newRotation: Int) {
|
||||
callManager.setDeviceRotation(newRotation)
|
||||
}
|
||||
var deviceRotation: Int = 0
|
||||
set(value) {
|
||||
field = value
|
||||
callManager.setDeviceRotation(value)
|
||||
}
|
||||
|
||||
val currentCallState
|
||||
get() = callManager.currentCallState
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package org.thoughtcrime.securesms.webrtc
|
||||
|
||||
import android.content.Context
|
||||
import org.session.libsignal.utilities.Log
|
||||
import org.session.libsignal.utilities.SettableFuture
|
||||
import org.thoughtcrime.securesms.webrtc.video.Camera
|
||||
import org.thoughtcrime.securesms.webrtc.video.CameraEventListener
|
||||
import org.thoughtcrime.securesms.webrtc.video.CameraState
|
||||
import org.thoughtcrime.securesms.webrtc.video.RotationVideoProcessor
|
||||
import org.thoughtcrime.securesms.webrtc.video.RotationVideoSink
|
||||
import org.webrtc.*
|
||||
import java.security.SecureRandom
|
||||
|
@ -74,7 +76,7 @@ class PeerConnectionWrapper(context: Context,
|
|||
context,
|
||||
rotationVideoSink
|
||||
)
|
||||
videoTrack.addSink(localRenderer)
|
||||
rotationVideoSink.setSink(localRenderer)
|
||||
videoTrack.setEnabled(false)
|
||||
mediaStream.addTrack(videoTrack)
|
||||
} else {
|
||||
|
@ -278,6 +280,7 @@ class PeerConnectionWrapper(context: Context,
|
|||
}
|
||||
|
||||
fun setDeviceRotation(rotation: Int) {
|
||||
Log.d("Loki", "rotation: $rotation")
|
||||
rotationVideoSink.rotation = rotation
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package org.thoughtcrime.securesms.webrtc.data
|
||||
|
||||
// get the video rotation from a specific rotation, locked into 90 degree
|
||||
// chunks offset by 45 degrees
|
||||
fun Int.quadrantRotation() = when (this % 360) {
|
||||
in 315 until 360,
|
||||
in 0 until 45 -> 90
|
||||
in 45 until 135 -> 180
|
||||
in 135 until 225 -> 270
|
||||
else -> 0
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package org.thoughtcrime.securesms.webrtc.video
|
||||
|
||||
import kotlinx.coroutines.newSingleThreadContext
|
||||
import org.webrtc.VideoFrame
|
||||
import org.webrtc.VideoProcessor
|
||||
import org.webrtc.VideoSink
|
||||
|
||||
class RotationVideoProcessor: VideoProcessor {
|
||||
|
||||
private var isCapturing: Boolean = true
|
||||
private var sink: VideoSink? = null
|
||||
|
||||
var rotation: Int = 0
|
||||
|
||||
override fun onCapturerStarted(p0: Boolean) {
|
||||
isCapturing = true
|
||||
}
|
||||
|
||||
override fun onCapturerStopped() {
|
||||
isCapturing = false
|
||||
}
|
||||
|
||||
override fun onFrameCaptured(frame: VideoFrame?) {
|
||||
val thisSink = sink ?: return
|
||||
val thisFrame = frame ?: return
|
||||
|
||||
val newFrame = VideoFrame(thisFrame.buffer, rotation, thisFrame.timestampNs)
|
||||
|
||||
thisSink.onFrame(newFrame)
|
||||
}
|
||||
|
||||
override fun setSink(newSink: VideoSink?) {
|
||||
sink = newSink
|
||||
}
|
||||
}
|
|
@ -1,17 +1,20 @@
|
|||
package org.thoughtcrime.securesms.webrtc.video
|
||||
|
||||
import org.session.libsignal.utilities.Log
|
||||
import org.thoughtcrime.securesms.webrtc.data.quadrantRotation
|
||||
import org.webrtc.CapturerObserver
|
||||
import org.webrtc.VideoFrame
|
||||
import org.webrtc.VideoProcessor
|
||||
import org.webrtc.VideoSink
|
||||
import java.lang.ref.SoftReference
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
class RotationVideoSink: CapturerObserver {
|
||||
class RotationVideoSink: CapturerObserver, VideoProcessor {
|
||||
|
||||
var rotation: Int = 0
|
||||
|
||||
private val capturing = AtomicBoolean(false)
|
||||
private var capturerObserver = SoftReference<CapturerObserver>(null)
|
||||
private var sink = SoftReference<VideoSink>(null)
|
||||
|
||||
override fun onCapturerStarted(ignored: Boolean) {
|
||||
capturing.set(true)
|
||||
|
@ -26,15 +29,19 @@ class RotationVideoSink: CapturerObserver {
|
|||
val observer = capturerObserver.get()
|
||||
if (videoFrame == null || observer == null || !capturing.get()) return
|
||||
|
||||
val quadrantRotation = when (rotation % 360) {
|
||||
in 0 until 90 -> 90
|
||||
in 90 until 180 -> 180
|
||||
in 180 until 270 -> 270
|
||||
else -> 0
|
||||
}
|
||||
val quadrantRotation = rotation.quadrantRotation()
|
||||
|
||||
val localRotation = 90
|
||||
|
||||
val newFrame = VideoFrame(videoFrame.buffer, quadrantRotation, videoFrame.timestampNs)
|
||||
val localFrame = VideoFrame(videoFrame.buffer, localRotation, videoFrame.timestampNs)
|
||||
|
||||
observer.onFrameCaptured(newFrame)
|
||||
sink.get()?.onFrame(localFrame)
|
||||
}
|
||||
|
||||
override fun setSink(sink: VideoSink?) {
|
||||
this.sink = SoftReference(sink)
|
||||
}
|
||||
|
||||
fun setObserver(videoSink: CapturerObserver?) {
|
||||
|
|
|
@ -9,15 +9,18 @@
|
|||
|
||||
<FrameLayout
|
||||
android:id="@+id/remote_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/remote_renderer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"/>
|
||||
</FrameLayout>
|
||||
<ImageView
|
||||
android:id="@+id/remote_recipient"
|
||||
|
|
Loading…
Reference in New Issue