Reuse transceivers (#24)

* protocol 4

* default to v4

* mediaStreamTrack.enabled

* track start

* private constructor

* remote audio/video tracks

* log sdp

* organize imports
This commit is contained in:
Hiroshi Horie
2021-10-26 02:46:10 +09:00
committed by GitHub
parent 330338afbd
commit 71a21f00b6
12 changed files with 120 additions and 27 deletions
+1
View File
@@ -40,6 +40,7 @@ extension ProtocolVersionExt on ProtocolVersion {
String toStringValue() => { String toStringValue() => {
ProtocolVersion.protocol2: '2', ProtocolVersion.protocol2: '2',
ProtocolVersion.protocol3: '3', ProtocolVersion.protocol3: '3',
ProtocolVersion.protocol4: '4',
}[this]!; }[this]!;
} }
+6 -6
View File
@@ -1,4 +1,6 @@
import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc;
import 'package:livekit_client/src/track/remote_audio_track.dart';
import 'package:livekit_client/src/track/remote_video_track.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import '../constants.dart'; import '../constants.dart';
@@ -8,10 +10,8 @@ import '../logger.dart';
import '../managers/event.dart'; import '../managers/event.dart';
import '../proto/livekit_models.pb.dart' as lk_models; import '../proto/livekit_models.pb.dart' as lk_models;
import '../signal_client.dart'; import '../signal_client.dart';
import '../track/audio_track.dart';
import '../track/remote_track_publication.dart'; import '../track/remote_track_publication.dart';
import '../track/track.dart'; import '../track/track.dart';
import '../track/video_track.dart';
import '../types.dart'; import '../types.dart';
import 'participant.dart'; import 'participant.dart';
@@ -91,14 +91,14 @@ class RemoteParticipant extends Participant {
final Track track; final Track track;
if (pub.kind == lk_models.TrackType.AUDIO) { if (pub.kind == lk_models.TrackType.AUDIO) {
// audio track // audio track
final audioTrack = AudioTrack(pub.name, mediaTrack, stream); track = RemoteAudioTrack(pub.name, mediaTrack, stream);
await audioTrack.start();
track = audioTrack;
} else { } else {
// video track // video track
track = VideoTrack(pub.name, mediaTrack, stream); track = RemoteVideoTrack(pub.name, mediaTrack, stream);
} }
await track.start();
pub.track = track; pub.track = track;
addTrackPublication(pub); addTrackPublication(pub);
+1
View File
@@ -495,6 +495,7 @@ class RTCEngine extends Disposable with EventsEmittable<EngineEvent> {
logger.fine('[$objectId] Received server offer(type: ${event.sd.type}, ' logger.fine('[$objectId] Received server offer(type: ${event.sd.type}, '
'${subscriber!.pc.signalingState})'); '${subscriber!.pc.signalingState})');
logger.finer('sdp: ${event.sd.sdp}');
await subscriber!.setRemoteDescription(event.sd); await subscriber!.setRemoteDescription(event.sd);
+1 -1
View File
@@ -24,7 +24,7 @@ class SignalClient extends Disposable with EventsEmittable<SignalEvent> {
LiveKitWebSocket? _ws; LiveKitWebSocket? _ws;
SignalClient({ SignalClient({
this.protocol = ProtocolVersion.protocol3, this.protocol = ProtocolVersion.protocol4,
}) { }) {
events.listen((event) { events.listen((event) {
logger.fine('[SignalEvent] $event'); logger.fine('[SignalEvent] $event');
+2 -12
View File
@@ -8,7 +8,7 @@ import 'package:synchronized/synchronized.dart' as sync;
import '../logger.dart'; import '../logger.dart';
import '../proto/livekit_models.pb.dart' as lk_models; import '../proto/livekit_models.pb.dart' as lk_models;
import '../support/native_audio.dart'; import '../support/native_audio.dart';
import '_audio_api.dart' if (dart.library.html) '_audio_html.dart' as audio;
import 'local_audio_track.dart'; import 'local_audio_track.dart';
import 'track.dart'; import 'track.dart';
@@ -22,7 +22,7 @@ enum AudioTrackState {
typedef ConfigureNativeAudioFunc = Future<NativeAudioConfiguration> Function( typedef ConfigureNativeAudioFunc = Future<NativeAudioConfiguration> Function(
AudioTrackState state); AudioTrackState state);
class AudioTrack extends Track { abstract class AudioTrack extends Track {
// it's possible to set custom function here to customize audio session configuration // it's possible to set custom function here to customize audio session configuration
static ConfigureNativeAudioFunc nativeAudioConfigurationForAudioTrackState = static ConfigureNativeAudioFunc nativeAudioConfigurationForAudioTrackState =
defaultNativeAudioConfigurationFunc; defaultNativeAudioConfigurationFunc;
@@ -50,10 +50,6 @@ class AudioTrack extends Track {
Future<bool> start() async { Future<bool> start() async {
final didStart = await super.start(); final didStart = await super.start();
if (didStart) { if (didStart) {
if (this is! LocalAudioTrack) {
audio.startAudio(getCid(), mediaStreamTrack);
}
// update counter // update counter
await _trackCounterLock.synchronized(() async { await _trackCounterLock.synchronized(() async {
if (this is LocalAudioTrack) { if (this is LocalAudioTrack) {
@@ -64,7 +60,6 @@ class AudioTrack extends Track {
await _onAudioTrackCountDidChange(); await _onAudioTrackCountDidChange();
}); });
} }
return didStart; return didStart;
} }
@@ -72,10 +67,6 @@ class AudioTrack extends Track {
Future<bool> stop() async { Future<bool> stop() async {
final didStop = await super.stop(); final didStop = await super.stop();
if (didStop) { if (didStop) {
await mediaStream?.dispose();
mediaStream = null;
audio.stopAudio(getCid());
// update counter // update counter
await _trackCounterLock.synchronized(() async { await _trackCounterLock.synchronized(() async {
if (this is LocalAudioTrack) { if (this is LocalAudioTrack) {
@@ -86,7 +77,6 @@ class AudioTrack extends Track {
await _onAudioTrackCountDidChange(); await _onAudioTrackCountDidChange();
}); });
} }
return didStop; return didStop;
} }
+12 -2
View File
@@ -7,7 +7,8 @@ import 'audio_track.dart';
import 'options.dart'; import 'options.dart';
class LocalAudioTrack extends AudioTrack { class LocalAudioTrack extends AudioTrack {
LocalAudioTrack( // private constructor
LocalAudioTrack._(
String name, String name,
rtc.MediaStreamTrack track, rtc.MediaStreamTrack track,
rtc.MediaStream stream, rtc.MediaStream stream,
@@ -29,6 +30,15 @@ class LocalAudioTrack extends AudioTrack {
if (stream.getAudioTracks().isEmpty) throw TrackCreateException(); if (stream.getAudioTracks().isEmpty) throw TrackCreateException();
return LocalAudioTrack('', stream.getAudioTracks().first, stream); return LocalAudioTrack._('', stream.getAudioTracks().first, stream);
}
@override
Future<bool> stop() async {
final didStop = await super.stop();
if (didStop) {
await mediaStreamTrack.stop();
}
return didStop;
} }
} }
+9
View File
@@ -92,6 +92,15 @@ class LocalVideoTrack extends VideoTrack {
if (stream.getVideoTracks().isEmpty) throw TrackCreateException(); if (stream.getVideoTracks().isEmpty) throw TrackCreateException();
return stream; return stream;
} }
@override
Future<bool> stop() async {
final didStop = await super.stop();
if (didStop) {
await mediaStreamTrack.stop();
}
return didStop;
}
} }
// //
+34
View File
@@ -0,0 +1,34 @@
import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc;
import '_audio_api.dart' if (dart.library.html) '_audio_html.dart' as audio;
import 'audio_track.dart';
class RemoteAudioTrack extends AudioTrack {
//
RemoteAudioTrack(
String name,
rtc.MediaStreamTrack track,
rtc.MediaStream stream,
) : super(name, track, stream);
@override
Future<bool> start() async {
final didStart = await super.start();
if (didStart) {
// web support
audio.startAudio(getCid(), mediaStreamTrack);
await enable();
}
return didStart;
}
@override
Future<bool> stop() async {
final didStop = await super.stop();
if (didStop) {
// web support
audio.stopAudio(getCid());
await disable();
}
return didStop;
}
}
+29
View File
@@ -0,0 +1,29 @@
import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc;
import 'package:livekit_client/src/track/video_track.dart';
class RemoteVideoTrack extends VideoTrack {
//
RemoteVideoTrack(
String name,
rtc.MediaStreamTrack mediaTrack,
rtc.MediaStream stream,
) : super(name, mediaTrack, stream);
@override
Future<bool> start() async {
final didStart = await super.start();
if (didStart) {
await enable();
}
return didStart;
}
@override
Future<bool> stop() async {
final didStop = await super.stop();
if (didStop) {
await disable();
}
return didStop;
}
}
+23 -5
View File
@@ -76,6 +76,8 @@ abstract class Track extends DisposableChangeNotifier
return false; return false;
} }
logger.fine('Track.start()');
_active = true; _active = true;
return true; return true;
} }
@@ -88,13 +90,29 @@ abstract class Track extends DisposableChangeNotifier
return false; return false;
} }
try { logger.fine('Track.stop()');
await mediaStreamTrack.stop();
} catch (_) {
logger.warning('[$objectId] rtc.mediaStreamTrack.stop() did throw ${_}');
}
_active = false; _active = false;
return true; return true;
} }
Future<void> enable() async {
logger.fine('Track.enable()');
try {
mediaStreamTrack.enabled = true;
} catch (_) {
logger.warning(
'[$objectId] set rtc.mediaStreamTrack.enabled did throw ${_}');
}
}
Future<void> disable() async {
logger.fine('Track.disable()');
try {
mediaStreamTrack.enabled = false;
} catch (_) {
logger.warning(
'[$objectId] set rtc.mediaStreamTrack.enabled did throw ${_}');
}
}
} }
+1 -1
View File
@@ -5,7 +5,7 @@ import '../proto/livekit_models.pb.dart' as lk_models;
import 'track.dart'; import 'track.dart';
/// A video track will notify when its mediaTrack has changed. /// A video track will notify when its mediaTrack has changed.
class VideoTrack extends Track { abstract class VideoTrack extends Track {
rtc.MediaStream _mediaStream; rtc.MediaStream _mediaStream;
VideoTrack( VideoTrack(
+1
View File
@@ -7,6 +7,7 @@ typedef CancelListenFunc = Function();
enum ProtocolVersion { enum ProtocolVersion {
protocol2, protocol2,
protocol3, protocol3,
protocol4,
} }
enum ConnectionState { enum ConnectionState {