David Liu

have users be response for creating and publishing tracks

<component name="ProjectDictionaryState">
<dictionary name="davidliu">
<words>
<w>capturer</w>
</words>
</dictionary>
</component>
\ No newline at end of file
... ...
... ... @@ -2,6 +2,5 @@ package io.livekit.android
data class ConnectOptions(
val sendAudio: Boolean = true,
val sendVideo: Boolean = true,
val placeholder: Unit = Unit
)
\ No newline at end of file
... ...
... ... @@ -4,11 +4,6 @@ import android.content.Context
import io.livekit.android.dagger.DaggerLiveKitComponent
import io.livekit.android.room.Room
import io.livekit.android.room.RoomListener
import io.livekit.android.room.track.LocalAudioTrack
import io.livekit.android.room.track.LocalVideoTrack
import org.webrtc.EglBase
import org.webrtc.MediaConstraints
import org.webrtc.PeerConnectionFactory
class LiveKit {
companion object {
... ... @@ -27,51 +22,15 @@ class LiveKit {
val component = DaggerLiveKitComponent
.factory()
.create(appContext)
.create(appContext.applicationContext)
val room = component.roomFactory()
.create(options)
room.listener = listener
room.connect(url, token)
val localParticipant = room.localParticipant
if (localParticipant != null) {
val factory = component.peerConnectionFactory()
if (options.sendAudio) {
val audioTrack = createLocalAudioTrack(factory)
localParticipant.publishAudioTrack(audioTrack)
audioTrack.enabled = true
}
if (options.sendVideo) {
val videoTrack = createLocalVideoTrack(
factory,
appContext,
component.eglBase()
)
localParticipant.publishVideoTrack(videoTrack)
videoTrack.startCapture()
}
}
return room
}
private fun createLocalVideoTrack(
peerConnectionFactory: PeerConnectionFactory,
context: Context,
rootEglBase: EglBase,
): LocalVideoTrack {
return LocalVideoTrack.createTrack(
peerConnectionFactory,
context,
true,
"LiveKit Video",
rootEglBase
)
}
private fun createLocalAudioTrack(factory: PeerConnectionFactory): LocalAudioTrack {
val audioConstraints = MediaConstraints()
return LocalAudioTrack.createTrack(factory, audioConstraints)
}
}
}
... ...
... ... @@ -77,11 +77,6 @@ class RTCModule {
}
return JavaAudioDeviceModule.builder(appContext)
.setSamplesReadyCallback(object : JavaAudioDeviceModule.SamplesReadyCallback {
override fun onWebRtcAudioRecordSamplesReady(samples: JavaAudioDeviceModule.AudioSamples?) {
Timber.v { "samples: $samples" }
}
})
.setUseHardwareAcousticEchoCanceler(true)
.setUseHardwareNoiseSuppressor(true)
.setAudioRecordErrorCallback(audioRecordErrorCallback)
... ...
package io.livekit.android.room
import android.content.Context
import com.github.ajalt.timberkt.Timber
import io.livekit.android.dagger.InjectionNames
import io.livekit.android.room.track.Track
import io.livekit.android.room.track.TrackException
import io.livekit.android.room.util.*
import io.livekit.android.util.CloseableCoroutineScope
... ... @@ -16,6 +14,7 @@ import livekit.LivekitRtc
import org.webrtc.*
import javax.inject.Inject
import javax.inject.Named
import javax.inject.Singleton
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
... ... @@ -23,6 +22,7 @@ import kotlin.coroutines.suspendCoroutine
/**
* @suppress
*/
@Singleton
class RTCEngine
@Inject
constructor(
... ...
... ... @@ -27,6 +27,7 @@ constructor(
@Assisted private val connectOptions: ConnectOptions,
private val engine: RTCEngine,
private val eglBase: EglBase,
private val localParticipantFactory: LocalParticipant.Factory
) : RTCEngine.Listener, ParticipantListener {
init {
engine.listener = this
... ... @@ -162,7 +163,7 @@ constructor(
return
}
val lp = LocalParticipant(response.participant, engine)
val lp = localParticipantFactory.create(response.participant)
lp.listener = this
localParticipant = lp
if (response.otherParticipantsList.isNotEmpty()) {
... ...
package io.livekit.android.room.participant
import android.content.Context
import com.github.ajalt.timberkt.Timber
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import io.livekit.android.room.RTCEngine
import io.livekit.android.room.track.*
import livekit.LivekitModels
import org.webrtc.DataChannel
import org.webrtc.RtpTransceiver
import java.util.*
class LocalParticipant(info: LivekitModels.ParticipantInfo, private val engine: RTCEngine) :
import org.webrtc.*
class LocalParticipant
@AssistedInject
internal constructor(
@Assisted
info: LivekitModels.ParticipantInfo,
private val engine: RTCEngine,
private val peerConnectionFactory: PeerConnectionFactory,
private val context: Context,
private val eglBase: EglBase,
) :
Participant(info.sid, info.identity) {
init {
... ... @@ -18,6 +29,24 @@ class LocalParticipant(info: LivekitModels.ParticipantInfo, private val engine:
private val localTrackPublications
get() = tracks.values.toList()
fun createAudioTrack(
audioConstraints: MediaConstraints = MediaConstraints(),
name: String = ""
) = LocalAudioTrack.createTrack(peerConnectionFactory, audioConstraints, name)
fun createVideoTrack(
isScreencast: Boolean = false,
name: String = "",
): LocalVideoTrack {
return LocalVideoTrack.createTrack(
peerConnectionFactory,
context,
isScreencast,
name,
eglBase
)
}
suspend fun publishAudioTrack(
track: LocalAudioTrack,
publishListener: PublishListener? = null
... ... @@ -147,4 +176,9 @@ class LocalParticipant(info: LivekitModels.ParticipantInfo, private val engine:
fun onPublishSuccess(publication: TrackPublication) {}
fun onPublishFailure(exception: Exception) {}
}
@AssistedFactory
interface Factory {
fun create(info: LivekitModels.ParticipantInfo): LocalParticipant
}
}
... ...
... ... @@ -4,6 +4,11 @@ import org.webrtc.MediaConstraints
import org.webrtc.PeerConnectionFactory
import java.util.*
/**
* Represents a local audio track (generally using the microphone as input).
*
* This class should not be constructed directly, but rather through [LocalParticipant]
*/
class LocalAudioTrack(
name: String,
audioOptions: AudioOptions? = null,
... ... @@ -19,9 +24,9 @@ class LocalAudioTrack(
private set
companion object {
fun createTrack(
internal fun createTrack(
factory: PeerConnectionFactory,
audioConstraints: MediaConstraints,
audioConstraints: MediaConstraints = MediaConstraints(),
name: String = ""
): LocalAudioTrack {
... ...
... ... @@ -5,7 +5,11 @@ import com.github.ajalt.timberkt.Timber
import org.webrtc.*
import java.util.*
/**
* A representation of a local video track (generally input coming from camera or screen).
*
* [startCapture] should be called before use.
*/
class LocalVideoTrack(
private val capturer: VideoCapturer,
private val source: VideoSource,
... ... @@ -20,19 +24,18 @@ class LocalVideoTrack(
internal fun createTrack(
peerConnectionFactory: PeerConnectionFactory,
context: Context,
enabled: Boolean,
isScreencast: Boolean,
name: String,
rootEglBase: EglBase,
): LocalVideoTrack {
val source = peerConnectionFactory.createVideoSource(false)
val source = peerConnectionFactory.createVideoSource(isScreencast)
val capturer = createVideoCapturer(context) ?: TODO()
capturer.initialize(
SurfaceTextureHelper.create("CaptureThread", rootEglBase.eglBaseContext),
SurfaceTextureHelper.create("VideoCaptureThread", rootEglBase.eglBaseContext),
context,
source.capturerObserver
)
val track = peerConnectionFactory.createVideoTrack(UUID.randomUUID().toString(), source)
track.setEnabled(enabled)
return LocalVideoTrack(
capturer = capturer,
... ...
... ... @@ -30,9 +30,17 @@ class CallViewModel(
application,
url,
token,
ConnectOptions(true),
ConnectOptions(),
this@CallViewModel
)
val localParticipant = room.localParticipant
val audioTrack = localParticipant.createAudioTrack()
localParticipant.publishAudioTrack(audioTrack)
val videoTrack = localParticipant.createVideoTrack()
localParticipant.publishVideoTrack(videoTrack)
videoTrack.startCapture()
updateParticipants(room)
mutableRoom.value = room
}
... ... @@ -50,7 +58,6 @@ class CallViewModel(
override fun onCleared() {
super.onCleared()
mutableRoom.value?.disconnect()
mutableRoom.value = null
}
override fun onDisconnect(room: Room, error: Exception?) {
... ...
... ... @@ -20,9 +20,8 @@
<org.webrtc.SurfaceViewRenderer
android:id="@+id/pip_video_view"
android:layout_height="144dp"
android:layout_width="0dp"
android:layout_width="144dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_margin="16dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
... ...