正在显示
11 个修改的文件
包含
77 行增加
和
68 行删除
.idea/dictionaries/davidliu.xml
0 → 100644
| @@ -4,11 +4,6 @@ import android.content.Context | @@ -4,11 +4,6 @@ import android.content.Context | ||
| 4 | import io.livekit.android.dagger.DaggerLiveKitComponent | 4 | import io.livekit.android.dagger.DaggerLiveKitComponent |
| 5 | import io.livekit.android.room.Room | 5 | import io.livekit.android.room.Room |
| 6 | import io.livekit.android.room.RoomListener | 6 | import io.livekit.android.room.RoomListener |
| 7 | -import io.livekit.android.room.track.LocalAudioTrack | ||
| 8 | -import io.livekit.android.room.track.LocalVideoTrack | ||
| 9 | -import org.webrtc.EglBase | ||
| 10 | -import org.webrtc.MediaConstraints | ||
| 11 | -import org.webrtc.PeerConnectionFactory | ||
| 12 | 7 | ||
| 13 | class LiveKit { | 8 | class LiveKit { |
| 14 | companion object { | 9 | companion object { |
| @@ -27,51 +22,15 @@ class LiveKit { | @@ -27,51 +22,15 @@ class LiveKit { | ||
| 27 | 22 | ||
| 28 | val component = DaggerLiveKitComponent | 23 | val component = DaggerLiveKitComponent |
| 29 | .factory() | 24 | .factory() |
| 30 | - .create(appContext) | 25 | + .create(appContext.applicationContext) |
| 31 | 26 | ||
| 32 | val room = component.roomFactory() | 27 | val room = component.roomFactory() |
| 33 | .create(options) | 28 | .create(options) |
| 34 | room.listener = listener | 29 | room.listener = listener |
| 35 | room.connect(url, token) | 30 | room.connect(url, token) |
| 36 | 31 | ||
| 37 | - val localParticipant = room.localParticipant | ||
| 38 | - if (localParticipant != null) { | ||
| 39 | - val factory = component.peerConnectionFactory() | ||
| 40 | - if (options.sendAudio) { | ||
| 41 | - val audioTrack = createLocalAudioTrack(factory) | ||
| 42 | - localParticipant.publishAudioTrack(audioTrack) | ||
| 43 | - audioTrack.enabled = true | ||
| 44 | - } | ||
| 45 | - if (options.sendVideo) { | ||
| 46 | - val videoTrack = createLocalVideoTrack( | ||
| 47 | - factory, | ||
| 48 | - appContext, | ||
| 49 | - component.eglBase() | ||
| 50 | - ) | ||
| 51 | - localParticipant.publishVideoTrack(videoTrack) | ||
| 52 | - videoTrack.startCapture() | ||
| 53 | - } | ||
| 54 | - } | ||
| 55 | return room | 32 | return room |
| 56 | } | 33 | } |
| 57 | 34 | ||
| 58 | - private fun createLocalVideoTrack( | ||
| 59 | - peerConnectionFactory: PeerConnectionFactory, | ||
| 60 | - context: Context, | ||
| 61 | - rootEglBase: EglBase, | ||
| 62 | - ): LocalVideoTrack { | ||
| 63 | - return LocalVideoTrack.createTrack( | ||
| 64 | - peerConnectionFactory, | ||
| 65 | - context, | ||
| 66 | - true, | ||
| 67 | - "LiveKit Video", | ||
| 68 | - rootEglBase | ||
| 69 | - ) | ||
| 70 | - } | ||
| 71 | - | ||
| 72 | - private fun createLocalAudioTrack(factory: PeerConnectionFactory): LocalAudioTrack { | ||
| 73 | - val audioConstraints = MediaConstraints() | ||
| 74 | - return LocalAudioTrack.createTrack(factory, audioConstraints) | ||
| 75 | - } | ||
| 76 | } | 35 | } |
| 77 | } | 36 | } |
| @@ -77,11 +77,6 @@ class RTCModule { | @@ -77,11 +77,6 @@ class RTCModule { | ||
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | return JavaAudioDeviceModule.builder(appContext) | 79 | return JavaAudioDeviceModule.builder(appContext) |
| 80 | - .setSamplesReadyCallback(object : JavaAudioDeviceModule.SamplesReadyCallback { | ||
| 81 | - override fun onWebRtcAudioRecordSamplesReady(samples: JavaAudioDeviceModule.AudioSamples?) { | ||
| 82 | - Timber.v { "samples: $samples" } | ||
| 83 | - } | ||
| 84 | - }) | ||
| 85 | .setUseHardwareAcousticEchoCanceler(true) | 80 | .setUseHardwareAcousticEchoCanceler(true) |
| 86 | .setUseHardwareNoiseSuppressor(true) | 81 | .setUseHardwareNoiseSuppressor(true) |
| 87 | .setAudioRecordErrorCallback(audioRecordErrorCallback) | 82 | .setAudioRecordErrorCallback(audioRecordErrorCallback) |
| 1 | package io.livekit.android.room | 1 | package io.livekit.android.room |
| 2 | 2 | ||
| 3 | -import android.content.Context | ||
| 4 | import com.github.ajalt.timberkt.Timber | 3 | import com.github.ajalt.timberkt.Timber |
| 5 | import io.livekit.android.dagger.InjectionNames | 4 | import io.livekit.android.dagger.InjectionNames |
| 6 | -import io.livekit.android.room.track.Track | ||
| 7 | import io.livekit.android.room.track.TrackException | 5 | import io.livekit.android.room.track.TrackException |
| 8 | import io.livekit.android.room.util.* | 6 | import io.livekit.android.room.util.* |
| 9 | import io.livekit.android.util.CloseableCoroutineScope | 7 | import io.livekit.android.util.CloseableCoroutineScope |
| @@ -16,6 +14,7 @@ import livekit.LivekitRtc | @@ -16,6 +14,7 @@ import livekit.LivekitRtc | ||
| 16 | import org.webrtc.* | 14 | import org.webrtc.* |
| 17 | import javax.inject.Inject | 15 | import javax.inject.Inject |
| 18 | import javax.inject.Named | 16 | import javax.inject.Named |
| 17 | +import javax.inject.Singleton | ||
| 19 | import kotlin.coroutines.Continuation | 18 | import kotlin.coroutines.Continuation |
| 20 | import kotlin.coroutines.resume | 19 | import kotlin.coroutines.resume |
| 21 | import kotlin.coroutines.suspendCoroutine | 20 | import kotlin.coroutines.suspendCoroutine |
| @@ -23,6 +22,7 @@ import kotlin.coroutines.suspendCoroutine | @@ -23,6 +22,7 @@ import kotlin.coroutines.suspendCoroutine | ||
| 23 | /** | 22 | /** |
| 24 | * @suppress | 23 | * @suppress |
| 25 | */ | 24 | */ |
| 25 | +@Singleton | ||
| 26 | class RTCEngine | 26 | class RTCEngine |
| 27 | @Inject | 27 | @Inject |
| 28 | constructor( | 28 | constructor( |
| @@ -27,6 +27,7 @@ constructor( | @@ -27,6 +27,7 @@ constructor( | ||
| 27 | @Assisted private val connectOptions: ConnectOptions, | 27 | @Assisted private val connectOptions: ConnectOptions, |
| 28 | private val engine: RTCEngine, | 28 | private val engine: RTCEngine, |
| 29 | private val eglBase: EglBase, | 29 | private val eglBase: EglBase, |
| 30 | + private val localParticipantFactory: LocalParticipant.Factory | ||
| 30 | ) : RTCEngine.Listener, ParticipantListener { | 31 | ) : RTCEngine.Listener, ParticipantListener { |
| 31 | init { | 32 | init { |
| 32 | engine.listener = this | 33 | engine.listener = this |
| @@ -162,7 +163,7 @@ constructor( | @@ -162,7 +163,7 @@ constructor( | ||
| 162 | return | 163 | return |
| 163 | } | 164 | } |
| 164 | 165 | ||
| 165 | - val lp = LocalParticipant(response.participant, engine) | 166 | + val lp = localParticipantFactory.create(response.participant) |
| 166 | lp.listener = this | 167 | lp.listener = this |
| 167 | localParticipant = lp | 168 | localParticipant = lp |
| 168 | if (response.otherParticipantsList.isNotEmpty()) { | 169 | if (response.otherParticipantsList.isNotEmpty()) { |
| 1 | package io.livekit.android.room.participant | 1 | package io.livekit.android.room.participant |
| 2 | 2 | ||
| 3 | +import android.content.Context | ||
| 3 | import com.github.ajalt.timberkt.Timber | 4 | import com.github.ajalt.timberkt.Timber |
| 5 | +import dagger.assisted.Assisted | ||
| 6 | +import dagger.assisted.AssistedFactory | ||
| 7 | +import dagger.assisted.AssistedInject | ||
| 4 | import io.livekit.android.room.RTCEngine | 8 | import io.livekit.android.room.RTCEngine |
| 5 | import io.livekit.android.room.track.* | 9 | import io.livekit.android.room.track.* |
| 6 | import livekit.LivekitModels | 10 | import livekit.LivekitModels |
| 7 | -import org.webrtc.DataChannel | ||
| 8 | -import org.webrtc.RtpTransceiver | ||
| 9 | -import java.util.* | ||
| 10 | - | ||
| 11 | -class LocalParticipant(info: LivekitModels.ParticipantInfo, private val engine: RTCEngine) : | 11 | +import org.webrtc.* |
| 12 | + | ||
| 13 | +class LocalParticipant | ||
| 14 | +@AssistedInject | ||
| 15 | +internal constructor( | ||
| 16 | + @Assisted | ||
| 17 | + info: LivekitModels.ParticipantInfo, | ||
| 18 | + private val engine: RTCEngine, | ||
| 19 | + private val peerConnectionFactory: PeerConnectionFactory, | ||
| 20 | + private val context: Context, | ||
| 21 | + private val eglBase: EglBase, | ||
| 22 | +) : | ||
| 12 | Participant(info.sid, info.identity) { | 23 | Participant(info.sid, info.identity) { |
| 13 | 24 | ||
| 14 | init { | 25 | init { |
| @@ -18,6 +29,24 @@ class LocalParticipant(info: LivekitModels.ParticipantInfo, private val engine: | @@ -18,6 +29,24 @@ class LocalParticipant(info: LivekitModels.ParticipantInfo, private val engine: | ||
| 18 | private val localTrackPublications | 29 | private val localTrackPublications |
| 19 | get() = tracks.values.toList() | 30 | get() = tracks.values.toList() |
| 20 | 31 | ||
| 32 | + fun createAudioTrack( | ||
| 33 | + audioConstraints: MediaConstraints = MediaConstraints(), | ||
| 34 | + name: String = "" | ||
| 35 | + ) = LocalAudioTrack.createTrack(peerConnectionFactory, audioConstraints, name) | ||
| 36 | + | ||
| 37 | + fun createVideoTrack( | ||
| 38 | + isScreencast: Boolean = false, | ||
| 39 | + name: String = "", | ||
| 40 | + ): LocalVideoTrack { | ||
| 41 | + return LocalVideoTrack.createTrack( | ||
| 42 | + peerConnectionFactory, | ||
| 43 | + context, | ||
| 44 | + isScreencast, | ||
| 45 | + name, | ||
| 46 | + eglBase | ||
| 47 | + ) | ||
| 48 | + } | ||
| 49 | + | ||
| 21 | suspend fun publishAudioTrack( | 50 | suspend fun publishAudioTrack( |
| 22 | track: LocalAudioTrack, | 51 | track: LocalAudioTrack, |
| 23 | publishListener: PublishListener? = null | 52 | publishListener: PublishListener? = null |
| @@ -147,4 +176,9 @@ class LocalParticipant(info: LivekitModels.ParticipantInfo, private val engine: | @@ -147,4 +176,9 @@ class LocalParticipant(info: LivekitModels.ParticipantInfo, private val engine: | ||
| 147 | fun onPublishSuccess(publication: TrackPublication) {} | 176 | fun onPublishSuccess(publication: TrackPublication) {} |
| 148 | fun onPublishFailure(exception: Exception) {} | 177 | fun onPublishFailure(exception: Exception) {} |
| 149 | } | 178 | } |
| 179 | + | ||
| 180 | + @AssistedFactory | ||
| 181 | + interface Factory { | ||
| 182 | + fun create(info: LivekitModels.ParticipantInfo): LocalParticipant | ||
| 183 | + } | ||
| 150 | } | 184 | } |
| @@ -4,6 +4,11 @@ import org.webrtc.MediaConstraints | @@ -4,6 +4,11 @@ import org.webrtc.MediaConstraints | ||
| 4 | import org.webrtc.PeerConnectionFactory | 4 | import org.webrtc.PeerConnectionFactory |
| 5 | import java.util.* | 5 | import java.util.* |
| 6 | 6 | ||
| 7 | +/** | ||
| 8 | + * Represents a local audio track (generally using the microphone as input). | ||
| 9 | + * | ||
| 10 | + * This class should not be constructed directly, but rather through [LocalParticipant] | ||
| 11 | + */ | ||
| 7 | class LocalAudioTrack( | 12 | class LocalAudioTrack( |
| 8 | name: String, | 13 | name: String, |
| 9 | audioOptions: AudioOptions? = null, | 14 | audioOptions: AudioOptions? = null, |
| @@ -19,9 +24,9 @@ class LocalAudioTrack( | @@ -19,9 +24,9 @@ class LocalAudioTrack( | ||
| 19 | private set | 24 | private set |
| 20 | 25 | ||
| 21 | companion object { | 26 | companion object { |
| 22 | - fun createTrack( | 27 | + internal fun createTrack( |
| 23 | factory: PeerConnectionFactory, | 28 | factory: PeerConnectionFactory, |
| 24 | - audioConstraints: MediaConstraints, | 29 | + audioConstraints: MediaConstraints = MediaConstraints(), |
| 25 | name: String = "" | 30 | name: String = "" |
| 26 | ): LocalAudioTrack { | 31 | ): LocalAudioTrack { |
| 27 | 32 |
| @@ -5,7 +5,11 @@ import com.github.ajalt.timberkt.Timber | @@ -5,7 +5,11 @@ import com.github.ajalt.timberkt.Timber | ||
| 5 | import org.webrtc.* | 5 | import org.webrtc.* |
| 6 | import java.util.* | 6 | import java.util.* |
| 7 | 7 | ||
| 8 | - | 8 | +/** |
| 9 | + * A representation of a local video track (generally input coming from camera or screen). | ||
| 10 | + * | ||
| 11 | + * [startCapture] should be called before use. | ||
| 12 | + */ | ||
| 9 | class LocalVideoTrack( | 13 | class LocalVideoTrack( |
| 10 | private val capturer: VideoCapturer, | 14 | private val capturer: VideoCapturer, |
| 11 | private val source: VideoSource, | 15 | private val source: VideoSource, |
| @@ -20,19 +24,18 @@ class LocalVideoTrack( | @@ -20,19 +24,18 @@ class LocalVideoTrack( | ||
| 20 | internal fun createTrack( | 24 | internal fun createTrack( |
| 21 | peerConnectionFactory: PeerConnectionFactory, | 25 | peerConnectionFactory: PeerConnectionFactory, |
| 22 | context: Context, | 26 | context: Context, |
| 23 | - enabled: Boolean, | 27 | + isScreencast: Boolean, |
| 24 | name: String, | 28 | name: String, |
| 25 | rootEglBase: EglBase, | 29 | rootEglBase: EglBase, |
| 26 | ): LocalVideoTrack { | 30 | ): LocalVideoTrack { |
| 27 | - val source = peerConnectionFactory.createVideoSource(false) | 31 | + val source = peerConnectionFactory.createVideoSource(isScreencast) |
| 28 | val capturer = createVideoCapturer(context) ?: TODO() | 32 | val capturer = createVideoCapturer(context) ?: TODO() |
| 29 | capturer.initialize( | 33 | capturer.initialize( |
| 30 | - SurfaceTextureHelper.create("CaptureThread", rootEglBase.eglBaseContext), | 34 | + SurfaceTextureHelper.create("VideoCaptureThread", rootEglBase.eglBaseContext), |
| 31 | context, | 35 | context, |
| 32 | source.capturerObserver | 36 | source.capturerObserver |
| 33 | ) | 37 | ) |
| 34 | val track = peerConnectionFactory.createVideoTrack(UUID.randomUUID().toString(), source) | 38 | val track = peerConnectionFactory.createVideoTrack(UUID.randomUUID().toString(), source) |
| 35 | - track.setEnabled(enabled) | ||
| 36 | 39 | ||
| 37 | return LocalVideoTrack( | 40 | return LocalVideoTrack( |
| 38 | capturer = capturer, | 41 | capturer = capturer, |
| @@ -30,9 +30,17 @@ class CallViewModel( | @@ -30,9 +30,17 @@ class CallViewModel( | ||
| 30 | application, | 30 | application, |
| 31 | url, | 31 | url, |
| 32 | token, | 32 | token, |
| 33 | - ConnectOptions(true), | 33 | + ConnectOptions(), |
| 34 | this@CallViewModel | 34 | this@CallViewModel |
| 35 | ) | 35 | ) |
| 36 | + | ||
| 37 | + val localParticipant = room.localParticipant | ||
| 38 | + val audioTrack = localParticipant.createAudioTrack() | ||
| 39 | + localParticipant.publishAudioTrack(audioTrack) | ||
| 40 | + val videoTrack = localParticipant.createVideoTrack() | ||
| 41 | + localParticipant.publishVideoTrack(videoTrack) | ||
| 42 | + videoTrack.startCapture() | ||
| 43 | + | ||
| 36 | updateParticipants(room) | 44 | updateParticipants(room) |
| 37 | mutableRoom.value = room | 45 | mutableRoom.value = room |
| 38 | } | 46 | } |
| @@ -50,7 +58,6 @@ class CallViewModel( | @@ -50,7 +58,6 @@ class CallViewModel( | ||
| 50 | override fun onCleared() { | 58 | override fun onCleared() { |
| 51 | super.onCleared() | 59 | super.onCleared() |
| 52 | mutableRoom.value?.disconnect() | 60 | mutableRoom.value?.disconnect() |
| 53 | - mutableRoom.value = null | ||
| 54 | } | 61 | } |
| 55 | 62 | ||
| 56 | override fun onDisconnect(room: Room, error: Exception?) { | 63 | override fun onDisconnect(room: Room, error: Exception?) { |
| @@ -20,9 +20,8 @@ | @@ -20,9 +20,8 @@ | ||
| 20 | <org.webrtc.SurfaceViewRenderer | 20 | <org.webrtc.SurfaceViewRenderer |
| 21 | android:id="@+id/pip_video_view" | 21 | android:id="@+id/pip_video_view" |
| 22 | android:layout_height="144dp" | 22 | android:layout_height="144dp" |
| 23 | - android:layout_width="0dp" | 23 | + android:layout_width="144dp" |
| 24 | app:layout_constraintBottom_toBottomOf="parent" | 24 | app:layout_constraintBottom_toBottomOf="parent" |
| 25 | app:layout_constraintEnd_toEndOf="parent" | 25 | app:layout_constraintEnd_toEndOf="parent" |
| 26 | - app:layout_constraintStart_toStartOf="parent" | ||
| 27 | android:layout_margin="16dp" /> | 26 | android:layout_margin="16dp" /> |
| 28 | </androidx.constraintlayout.widget.ConstraintLayout> | 27 | </androidx.constraintlayout.widget.ConstraintLayout> |
-
请 注册 或 登录 后发表评论