davidliu
Committed by GitHub

Fix race condition with videoTrack.addRenderer (#448)

... ... @@ -52,6 +52,16 @@ abstract class Track(
var statsGetter: RTCStatsGetter? = null
/**
* [MediaStreamTrack] doesn't expose a way to tell if it's disposed. Track it here.
* This can only be safely accessed on the rtc thread.
*
* Note: [MediaStreamTrack] can still be disposed if we don't own it, so this isn't necessarily safe,
* however generally all the tracks passed into this class are owned by this class.
*/
internal var isDisposed = false
private set
/**
* Return the [RTCStatsReport] for this track, or null if none is available.
*/
suspend fun getRTCStats(): RTCStatsReport? = statsGetter?.getStats()
... ... @@ -172,6 +182,7 @@ abstract class Track(
*/
open fun dispose() {
executeBlockingOnRTCThread {
isDisposed = true
rtcTrack.dispose()
}
}
... ...
... ... @@ -35,8 +35,10 @@ abstract class VideoTrack(name: String, override val rtcTrack: VideoTrack) :
*/
open fun addRenderer(renderer: VideoSink) {
executeBlockingOnRTCThread {
sinks.add(renderer)
rtcTrack.addSink(renderer)
if (!isDisposed) {
sinks.add(renderer)
rtcTrack.addSink(renderer)
}
}
}
... ... @@ -45,15 +47,19 @@ abstract class VideoTrack(name: String, override val rtcTrack: VideoTrack) :
*/
open fun removeRenderer(renderer: VideoSink) {
executeBlockingOnRTCThread {
rtcTrack.removeSink(renderer)
sinks.remove(renderer)
if (!isDisposed) {
rtcTrack.removeSink(renderer)
sinks.remove(renderer)
}
}
}
override fun stop() {
executeBlockingOnRTCThread {
for (sink in sinks) {
rtcTrack.removeSink(sink)
if (!isDisposed) {
for (sink in sinks) {
rtcTrack.removeSink(sink)
}
}
sinks.clear()
}
... ...