Stream State Update (#53)

* implemented

* update docs
This commit is contained in:
Hiroshi Horie
2021-12-11 14:18:35 +07:00
committed by GitHub
parent 7e1164a74c
commit 9c573f4924
8 changed files with 80 additions and 0 deletions
+14
View File
@@ -186,6 +186,20 @@ class TrackUnmutedEvent with RoomEvent, ParticipantEvent {
}); });
} }
/// The [StreamState] on the [RemoteTrackPublication] has updated by the server.
/// See [RemoteTrackPublication.streamState] for more information.
/// Emitted by [Room] and [RemoteParticipant].
class TrackStreamStateUpdatedEvent with RoomEvent, ParticipantEvent {
final RemoteParticipant participant;
final RemoteTrackPublication trackPublication;
final StreamState streamState;
const TrackStreamStateUpdatedEvent({
required this.participant,
required this.trackPublication,
required this.streamState,
});
}
/// Participant metadata is a simple way for app-specific state to be pushed to /// Participant metadata is a simple way for app-specific state to be pushed to
/// all users. When RoomService.UpdateParticipantMetadata is called to change a /// all users. When RoomService.UpdateParticipantMetadata is called to change a
/// [Participant]'s state, *all* [Participant]s in the room will fire this event. /// [Participant]'s state, *all* [Participant]s in the room will fire this event.
+8
View File
@@ -124,3 +124,11 @@ extension LKTrackSourceExt on TrackSource {
}[this] ?? }[this] ??
lk_models.TrackSource.UNKNOWN; lk_models.TrackSource.UNKNOWN;
} }
extension PBStreamStateExt on lk_rtc.StreamState {
StreamState toLKType() =>
<lk_rtc.StreamState, StreamState>{
lk_rtc.StreamState.ACTIVE: StreamState.active,
}[this] ??
StreamState.paused;
}
+8
View File
@@ -185,3 +185,11 @@ class SignalMuteTrackEvent with SignalEvent {
required this.muted, required this.muted,
}); });
} }
@internal
class SignalStreamStateUpdatedEvent with SignalEvent, EngineEvent {
final List<lk_rtc.StreamStateInfo> updates;
const SignalStreamStateUpdatedEvent({
required this.updates,
});
}
@@ -13,6 +13,7 @@ import '../participant/remote_participant.dart';
import '../proto/livekit_models.pb.dart' as lk_models; import '../proto/livekit_models.pb.dart' as lk_models;
import '../proto/livekit_rtc.pb.dart' as lk_rtc; import '../proto/livekit_rtc.pb.dart' as lk_rtc;
import '../track/remote.dart'; import '../track/remote.dart';
import '../types.dart';
import '../utils.dart'; import '../utils.dart';
import 'track_publication.dart'; import 'track_publication.dart';
@@ -40,6 +41,27 @@ class RemoteTrackPublication<T extends RemoteTrack>
lk_models.VideoQuality _videoQuality = lk_models.VideoQuality.HIGH; lk_models.VideoQuality _videoQuality = lk_models.VideoQuality.HIGH;
lk_models.VideoQuality get videoQuality => _videoQuality; lk_models.VideoQuality get videoQuality => _videoQuality;
StreamState _streamState = StreamState.paused;
/// The server may pause the track when they are bandwidth limitations and resume
/// when there is more capacity. This property will be updated when the track is
/// paused / resumed by the server. See [TrackStreamStateUpdatedEvent] for the
/// relevant event.
StreamState get streamState => _streamState;
@internal
Future<void> updateStreamState(StreamState streamState) async {
// return if no change
if (_streamState == streamState) return;
_streamState = streamState;
[participant.events, participant.room.events]
.emit(TrackStreamStateUpdatedEvent(
participant: participant,
trackPublication: this,
streamState: streamState,
));
}
// used to report renderer visibility to the server // used to report renderer visibility to the server
// and optimize // and optimize
final _visibilities = <String, RendererVisibility>{}; final _visibilities = <String, RendererVisibility>{};
+16
View File
@@ -152,6 +152,8 @@ class Room extends DisposableChangeNotifier with EventsEmittable<RoomEvent> {
(event) => _onSignalSpeakersChangedEvent(event.speakers)) (event) => _onSignalSpeakersChangedEvent(event.speakers))
..on<SignalConnectionQualityUpdateEvent>( ..on<SignalConnectionQualityUpdateEvent>(
(event) => _onSignalConnectionQualityUpdateEvent(event.updates)) (event) => _onSignalConnectionQualityUpdateEvent(event.updates))
..on<SignalStreamStateUpdatedEvent>(
(event) => _onSignalStreamStateUpdateEvent(event.updates))
..on<EngineDataPacketReceivedEvent>(_onDataMessageEvent) ..on<EngineDataPacketReceivedEvent>(_onDataMessageEvent)
..on<EngineRemoteMuteChangedEvent>((event) async { ..on<EngineRemoteMuteChangedEvent>((event) async {
final publication = localParticipant?.trackPublications[event.sid]; final publication = localParticipant?.trackPublications[event.sid];
@@ -364,6 +366,20 @@ class Room extends DisposableChangeNotifier with EventsEmittable<RoomEvent> {
} }
} }
void _onSignalStreamStateUpdateEvent(
List<lk_rtc.StreamStateInfo> updates) async {
for (final update in updates) {
// try to find RemoteParticipant
final participant = participants[update.participantSid];
if (participant == null) continue;
// try to find RemoteTrackPublication
final trackPublication = participant.trackPublications[update.trackSid];
if (trackPublication == null) continue;
// update the stream state
await trackPublication.updateStreamState(update.state.toLKType());
}
}
void _onDataMessageEvent(EngineDataPacketReceivedEvent dataPacketEvent) { void _onDataMessageEvent(EngineDataPacketReceivedEvent dataPacketEvent) {
// participant may be null if data is sent from Server-API // participant may be null if data is sent from Server-API
final senderSid = dataPacketEvent.packet.participantSid; final senderSid = dataPacketEvent.packet.participantSid;
+2
View File
@@ -563,6 +563,8 @@ class RTCEngine extends Disposable with EventsEmittable<EngineEvent> {
..on<SignalSpeakersChangedEvent>((event) => events.emit(event)) ..on<SignalSpeakersChangedEvent>((event) => events.emit(event))
// relay // relay
..on<SignalConnectionQualityUpdateEvent>((event) => events.emit(event)) ..on<SignalConnectionQualityUpdateEvent>((event) => events.emit(event))
// relay
..on<SignalStreamStateUpdatedEvent>((event) => events.emit(event))
..on<SignalLeaveEvent>((event) async { ..on<SignalLeaveEvent>((event) async {
await close(); await close();
events.emit(const EngineDisconnectedEvent()); events.emit(const EngineDisconnectedEvent());
+5
View File
@@ -250,6 +250,11 @@ class SignalClient extends Disposable with EventsEmittable<SignalEvent> {
muted: msg.mute.muted, muted: msg.mute.muted,
)); ));
break; break;
case lk_rtc.SignalResponse_Message.streamStateUpdate:
events.emit(SignalStreamStateUpdatedEvent(
updates: msg.streamStateUpdate.streamStates,
));
break;
default: default:
logger.warning('skipping unsupported signal message'); logger.warning('skipping unsupported signal message');
} }
+5
View File
@@ -37,6 +37,11 @@ enum TrackSource {
screenShareAudio, screenShareAudio,
} }
enum StreamState {
paused,
active,
}
enum CloseReason { enum CloseReason {
network, network,
// ... // ...