Toggle navigation
Toggle navigation
此项目
正在载入...
Sign in
xuning
/
livekitAndroidXuningTest
转到一个项目
Toggle navigation
项目
群组
代码片段
帮助
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
David Liu
2021-03-14 18:53:52 +0900
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
9b8c9efcba96d1742d1fea90e1422dd2d9183fe1
9b8c9efc
1 parent
6bbbc0e8
RemoteParticipant
隐藏空白字符变更
内嵌
并排对比
正在显示
6 个修改的文件
包含
364 行增加
和
7 行删除
livekit-android-sdk/src/main/java/io/livekit/android/room/participant/Participant.kt
livekit-android-sdk/src/main/java/io/livekit/android/room/participant/RemoteParticipant.kt
livekit-android-sdk/src/main/java/io/livekit/android/room/track/DataTrack.kt
livekit-android-sdk/src/main/java/io/livekit/android/room/track/DataTrackPublication.kt
livekit-android-sdk/src/main/java/io/livekit/android/room/track/RemoteDataTrack.kt
livekit-android-sdk/src/main/java/io/livekit/android/room/track/RemoteDataTrackPublication.kt
livekit-android-sdk/src/main/java/io/livekit/android/room/participant/Participant.kt
查看文件 @
9b8c9ef
package io.livekit.android.room.participant
import io.livekit.android.room.track.Track
import io.livekit.android.room.track.TrackPublication
import io.livekit.android.room.track.*
class Participant(val
sid: String, name: String? = null) {
open class Participant(var
sid: String, name: String? = null) {
inline class Sid(val sid: String)
var metadata: String? = null
...
...
@@ -20,10 +19,28 @@ class Participant(val sid: String, name: String? = null) {
var dataTracks = mutableMapOf<Track.Sid, TrackPublication>()
private set
fun addTrack(publication: TrackPublication){
fun addTrack(publication: TrackPublication)
{
tracks[publication.trackSid] = publication
when(publication) {
when (publication) {
is RemoteAudioTrackPublication -> audioTracks[publication.trackSid] = publication
is RemoteVideoTrackPublication -> videoTracks[publication.trackSid] = publication
is RemoteDataTrackPublication -> dataTracks[publication.trackSid] = publication
}
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as Participant
if (sid != other.sid) return false
return true
}
override fun hashCode(): Int {
return sid.hashCode()
}
}
\ No newline at end of file
...
...
livekit-android-sdk/src/main/java/io/livekit/android/room/participant/RemoteParticipant.kt
查看文件 @
9b8c9ef
package io.livekit.android.room.participant
class RemoteParticipant {
import com.github.ajalt.timberkt.Timber
import io.livekit.android.room.track.*
import io.livekit.android.util.CloseableCoroutineScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import livekit.Model
import org.webrtc.AudioTrack
import org.webrtc.DataChannel
import org.webrtc.MediaStreamTrack
import org.webrtc.VideoTrack
import java.nio.ByteBuffer
class RemoteParticipant(
sid: String, name: String? = null
) : Participant(sid, name), RemoteDataTrack.Listener {
constructor(info: Model.ParticipantInfo) : this(info.sid, info.identity) {
updateFromInfo(info)
}
val remoteAudioTracks
get() = audioTracks.values.toList()
val remoteVideoTracks
get() = videoTracks.values.toList()
val remoteDataTracks
get() = dataTracks.values.toList()
val listener: Listener? = null
var participantInfo: Model.ParticipantInfo? = null
val hasInfo
get() = participantInfo != null
private val coroutineScope = CloseableCoroutineScope(SupervisorJob())
fun getTrackPublication(sid: Track.Sid): RemoteTrackPublication? =
tracks[sid] as? RemoteTrackPublication
fun updateFromInfo(info: Model.ParticipantInfo) {
val hadInfo = hasInfo
sid = info.sid
name = info.identity
participantInfo = info
metadata = info.metadata
val validTrackPublication = mutableMapOf<Track.Sid, RemoteTrackPublication>()
val newTrackPublications = mutableMapOf<Track.Sid, RemoteTrackPublication>()
for (trackInfo in info.tracksList) {
val trackSid = Track.Sid(trackInfo.sid)
var publication = getTrackPublication(trackSid)
if (publication == null) {
publication = when (trackInfo.type) {
Model.TrackType.AUDIO -> RemoteAudioTrackPublication(trackInfo)
Model.TrackType.VIDEO -> RemoteVideoTrackPublication(trackInfo)
Model.TrackType.DATA -> RemoteDataTrackPublication(trackInfo)
Model.TrackType.UNRECOGNIZED -> throw TrackException.InvalidTrackTypeException()
null -> throw NullPointerException("trackInfo.type is null")
}
newTrackPublications[trackSid] = publication
addTrack(publication)
} else {
publication.updateFromInfo(trackInfo)
}
validTrackPublication[trackSid] = publication
}
if (hadInfo) {
for (publication in newTrackPublications.values) {
sendTrackPublishedEvent(publication)
}
}
val invalidKeys = tracks.keys - validTrackPublication.keys
for (invalidKey in invalidKeys) {
val publication = tracks[invalidKey] ?: continue
unpublishTrack(publication.trackSid, true)
}
}
fun addSubscribedMediaTrack(rtcTrack: MediaStreamTrack, sid: Track.Sid, triesLeft: Int = 20) {
val publication = getTrackPublication(sid)
val track: Track = when (val kind = rtcTrack.kind()) {
KIND_AUDIO -> RemoteAudioTrack(sid = sid, rtcTrack = rtcTrack as AudioTrack, name = "")
KIND_VIDEO -> RemoteVideoTrack(sid = sid, rtcTrack = rtcTrack as VideoTrack, name = "")
else -> throw TrackException.InvalidTrackTypeException("invalid track type: $kind")
}
if (publication == null) {
if (triesLeft == 0) {
val message = "Could not find published track with sid: $sid"
val exception = TrackException.InvalidTrackStateException(message)
Timber.e { "remote participant ${this.sid} --- $message" }
when (rtcTrack.kind()) {
KIND_AUDIO -> {
listener?.onFailToSubscribe(
audioTrack = track as RemoteAudioTrack,
exception = exception,
participant = this
)
}
KIND_VIDEO -> {
listener?.onFailToSubscribe(
videoTrack = track as RemoteVideoTrack,
exception = exception,
participant = this
)
}
}
} else {
coroutineScope.launch {
delay(150)
addSubscribedMediaTrack(rtcTrack, sid, triesLeft - 1)
}
}
return
}
val remoteTrack = track as RemoteTrack
publication.track = track
track.name = publication.trackName
remoteTrack.sid = publication.trackSid
when (publication) {
is RemoteAudioTrackPublication -> listener?.onSubscribe(publication, this)
is RemoteVideoTrackPublication -> listener?.onSubscribe(publication, this)
else -> throw TrackException.InvalidTrackTypeException()
}
}
fun addSubscribedDataTrack(rtcTrack: DataChannel, sid: Track.Sid, name: String) {
val track = RemoteDataTrack(sid, name, rtcTrack)
var publication = getTrackPublication(sid) as? RemoteDataTrackPublication
if (publication != null) {
publication.track = track
} else {
val trackInfo = Model.TrackInfo.newBuilder()
.setSid(sid.sid)
.setName(name)
.setType(Model.TrackType.DATA)
.build()
publication = RemoteDataTrackPublication(info = trackInfo, track = track)
addTrack(publication)
if (hasInfo) {
sendTrackPublishedEvent(publication)
}
}
rtcTrack.registerObserver(object : DataChannel.Observer {
override fun onBufferedAmountChange(previousAmount: Long) {}
override fun onStateChange() {
val newState = rtcTrack.state()
if (newState == DataChannel.State.CLOSED) {
listener?.onUnsubscribe(publication, this@RemoteParticipant)
}
}
override fun onMessage(buffer: DataChannel.Buffer) {
listener?.onReceive(buffer.data, publication, this@RemoteParticipant)
}
})
listener?.onSubscribe(dataTrack = publication, participant = this)
}
private fun unpublishTrack(trackSid: Track.Sid, sendUnpublish: Boolean) {
val publication = tracks.remove(trackSid) ?: return
when (publication) {
is RemoteAudioTrackPublication -> audioTracks.remove(trackSid)
is RemoteVideoTrackPublication -> videoTracks.remove(trackSid)
is RemoteDataTrackPublication -> {
dataTracks.remove(trackSid)
publication.dataTrack?.rtcTrack?.unregisterObserver()
}
else -> throw TrackException.InvalidTrackTypeException()
}
if (publication.track != null) {
// TODO: need to stop track?
publication.track
sendTrackUnsubscribedEvent(publication)
}
if (sendUnpublish) {
sendTrackUnpublishedEvent(publication)
}
}
private fun sendTrackUnsubscribedEvent(publication: TrackPublication) {
when (publication) {
is RemoteAudioTrackPublication -> listener?.onUnsubscribe(publication, this)
is RemoteVideoTrackPublication -> listener?.onUnsubscribe(publication, this)
is RemoteDataTrackPublication -> listener?.onUnsubscribe(publication, this)
else -> throw TrackException.InvalidTrackTypeException()
}
}
private fun sendTrackUnpublishedEvent(publication: TrackPublication) {
when (publication) {
is RemoteAudioTrackPublication -> listener?.onUnpublish(publication, this)
is RemoteVideoTrackPublication -> listener?.onUnpublish(publication, this)
is RemoteDataTrackPublication -> listener?.onUnpublish(publication, this)
else -> throw TrackException.InvalidTrackTypeException()
}
}
private fun sendTrackPublishedEvent(publication: RemoteTrackPublication) {
when (publication) {
is RemoteAudioTrackPublication -> listener?.onPublish(publication, this)
is RemoteVideoTrackPublication -> listener?.onPublish(publication, this)
is RemoteDataTrackPublication -> listener?.onPublish(publication, this)
else -> throw TrackException.InvalidTrackTypeException()
}
}
override fun onReceiveString(message: String, dataTrack: DataTrack) {
TODO("Not yet implemented")
}
override fun onReceiveData(message: DataChannel.Buffer, dataTrack: DataTrack) {
TODO("Not yet implemented")
}
companion object {
private const val KIND_AUDIO = "audio"
private const val KIND_VIDEO = "video"
}
interface Listener {
fun onPublish(audioTrack: RemoteAudioTrackPublication, participant: RemoteParticipant)
fun onUnpublish(audioTrack: RemoteAudioTrackPublication, participant: RemoteParticipant)
fun onPublish(videoTrack: RemoteVideoTrackPublication, participant: RemoteParticipant)
fun onUnpublish(videoTrack: RemoteVideoTrackPublication, participant: RemoteParticipant)
fun onPublish(dataTrack: RemoteDataTrackPublication, participant: RemoteParticipant)
fun onUnpublish(dataTrack: RemoteDataTrackPublication, participant: RemoteParticipant)
fun onEnable(audioTrack: RemoteAudioTrackPublication, participant: RemoteParticipant)
fun onDisable(audioTrack: RemoteAudioTrackPublication, participant: RemoteParticipant)
fun onEnable(videoTrack: RemoteVideoTrackPublication, participant: RemoteParticipant)
fun onDisable(videoTrack: RemoteVideoTrackPublication, participant: RemoteParticipant)
fun onSubscribe(audioTrack: RemoteAudioTrackPublication, participant: RemoteParticipant)
fun onFailToSubscribe(
audioTrack: RemoteAudioTrack,
exception: Exception,
participant: RemoteParticipant
)
fun onUnsubscribe(audioTrack: RemoteAudioTrackPublication, participant: RemoteParticipant)
fun onSubscribe(videoTrack: RemoteVideoTrackPublication, participant: RemoteParticipant)
fun onFailToSubscribe(
videoTrack: RemoteVideoTrack,
exception: Exception,
participant: RemoteParticipant
)
fun onUnsubscribe(videoTrack: RemoteVideoTrackPublication, participant: RemoteParticipant)
fun onSubscribe(dataTrack: RemoteDataTrackPublication, participant: RemoteParticipant)
fun onFailToSubscribe(
dataTrack: RemoteDataTrackPublication,
exception: Exception,
participant: RemoteParticipant
)
fun onUnsubscribe(dataTrack: RemoteDataTrackPublication, participant: RemoteParticipant)
fun onReceive(
data: ByteBuffer,
dataTrack: RemoteDataTrackPublication,
participant: RemoteParticipant
)
//fun networkQualityDidChange(networkQualityLevel: NetworkQualityLevel, participant: remoteParticipant)
fun switchedOffVideo(track: RemoteVideoTrack, participant: RemoteParticipant)
fun switchedOnVideo(track: RemoteVideoTrack, participant: RemoteParticipant)
// fun onChangePublishPriority(videoTrack: RemoteVideoTrackPublication, priority: PublishPriority, participant: RemoteParticipant)
// fun onChangePublishPriority(audioTrack: RemoteAudioTrackPublication, priority: PublishPriority, participant: RemoteParticipant)
// fun onChangePublishPriority(dataTrack: RemoteDataTrackPublication, priority: PublishPriority, participant: RemoteParticipant)
}
}
\ No newline at end of file
...
...
livekit-android-sdk/src/main/java/io/livekit/android/room/track/DataTrack.kt
0 → 100644
查看文件 @
9b8c9ef
package io.livekit.android.room.track
import org.webrtc.DataChannel
open class DataTrack(
name: String,
val rtcTrack: DataChannel
) : Track(name, stateFromRTCDataChannelState(rtcTrack.state())) {
/**
* TODO: These values are only available at [DataChannel.Init]
*/
val ordered: Boolean = TODO()
val maxPacketLifeTime: Int = TODO()
val maxRetransmits: Int = TODO()
}
\ No newline at end of file
...
...
livekit-android-sdk/src/main/java/io/livekit/android/room/track/DataTrackPublication.kt
0 → 100644
查看文件 @
9b8c9ef
package io.livekit.android.room.track
interface DataTrackPublication {
val dataTrack: DataTrack?
}
\ No newline at end of file
...
...
livekit-android-sdk/src/main/java/io/livekit/android/room/track/RemoteDataTrack.kt
0 → 100644
查看文件 @
9b8c9ef
package io.livekit.android.room.track
import org.webrtc.DataChannel
class RemoteDataTrack(
override var sid: Sid,
name: String,
rtcTrack: DataChannel
) :
DataTrack(name, rtcTrack),
RemoteTrack {
var listener: Listener? = null
interface Listener {
fun onReceiveString(message: String, dataTrack: DataTrack)
fun onReceiveData(message: DataChannel.Buffer, dataTrack: DataTrack)
}
}
\ No newline at end of file
...
...
livekit-android-sdk/src/main/java/io/livekit/android/room/track/RemoteDataTrackPublication.kt
0 → 100644
查看文件 @
9b8c9ef
package io.livekit.android.room.track
import livekit.Model
class RemoteDataTrackPublication(
info: Model.TrackInfo,
track: Track? = null
) : RemoteTrackPublication(info, track), DataTrackPublication {
override val dataTrack: DataTrack?
get() = track as? DataTrack
}
\ No newline at end of file
...
...
请
注册
或
登录
后发表评论