From 6240457333db33ae530d10c0b3bab37da70e883a Mon Sep 17 00:00:00 2001 From: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> Date: Tue, 26 Oct 2021 02:53:34 +0900 Subject: [PATCH] Option to control DTX (#25) * protocol 4 * default to v4 * mediaStreamTrack.enabled * track start * private constructor * remote audio/video tracks * log sdp * organize imports * dtx option (default true) --- example/lib/pages/connect.dart | 2 +- lib/src/options.dart | 28 ++++++++++++++++++---- lib/src/participant/local_participant.dart | 22 ++++++++++++----- lib/src/room.dart | 3 ++- lib/src/rtc_engine.dart | 8 ++++++- lib/src/signal_client.dart | 11 ++++++++- lib/src/utils.dart | 4 ++-- 7 files changed, 61 insertions(+), 17 deletions(-) diff --git a/example/lib/pages/connect.dart b/example/lib/pages/connect.dart index ff5cae0..b427215 100644 --- a/example/lib/pages/connect.dart +++ b/example/lib/pages/connect.dart @@ -79,7 +79,7 @@ class _ConnectPageState extends State { _uriCtrl.text, _tokenCtrl.text, options: ConnectOptions( - defaultPublishOptions: TrackPublishOptions( + defaultVideoPublishOptions: VideoPublishOptions( simulcast: _simulcast, ), ), diff --git a/lib/src/options.dart b/lib/src/options.dart index 026b37b..154c096 100644 --- a/lib/src/options.dart +++ b/lib/src/options.dart @@ -6,23 +6,27 @@ class ConnectOptions { /// Auto-subscribe to room tracks upon connect, defaults to true. final bool autoSubscribe; - /// Default options used when publishing a track - final TrackPublishOptions defaultPublishOptions; + /// Default options used when publishing a video track + final VideoPublishOptions defaultVideoPublishOptions; + + /// Default options used when publishing a audio track + final AudioPublishOptions defaultAudioPublishOptions; const ConnectOptions({ this.autoSubscribe = true, - this.defaultPublishOptions = const TrackPublishOptions(), + this.defaultVideoPublishOptions = const VideoPublishOptions(), + this.defaultAudioPublishOptions = const AudioPublishOptions(), }); } -class TrackPublishOptions { +class VideoPublishOptions { /// final VideoEncoding? videoEncoding; /// final bool simulcast; - const TrackPublishOptions({ + const VideoPublishOptions({ this.videoEncoding, this.simulcast = false, }); @@ -31,3 +35,17 @@ class TrackPublishOptions { String toString() => '${runtimeType}(videoEncoding: ${videoEncoding}, simulcast: ${simulcast})'; } + +class AudioPublishOptions { + /// DTX (Discontinuous Transmission) + /// https://en.wikipedia.org/wiki/Discontinuous_transmission + /// defaults to true + final bool dtx; + + const AudioPublishOptions({ + this.dtx = true, + }); + + @override + String toString() => '${runtimeType}(dtx: ${dtx})'; +} diff --git a/lib/src/participant/local_participant.dart b/lib/src/participant/local_participant.dart index 9bc14c6..13a5449 100644 --- a/lib/src/participant/local_participant.dart +++ b/lib/src/participant/local_participant.dart @@ -23,12 +23,15 @@ class LocalParticipant extends Participant { @internal final RTCEngine engine; @internal - final TrackPublishOptions? defaultPublishOptions; + final VideoPublishOptions? defaultVideoPublishOptions; + @internal + final AudioPublishOptions? defaultAudioPublishOptions; LocalParticipant({ required this.engine, required lk_models.ParticipantInfo info, - this.defaultPublishOptions, + this.defaultVideoPublishOptions, + this.defaultAudioPublishOptions, required EventsEmitter roomEvents, }) : super( info.sid, @@ -39,16 +42,23 @@ class LocalParticipant extends Participant { } /// publish an audio track to the room - Future publishAudioTrack(LocalAudioTrack track) async { + Future publishAudioTrack( + LocalAudioTrack track, { + AudioPublishOptions? options, + }) async { if (audioTracks.any( (e) => e.track?.mediaStreamTrack.id == track.mediaStreamTrack.id)) { throw TrackPublishException('track already exists'); } + // Use defaultPublishOptions if options is null + options = options ?? defaultAudioPublishOptions; + final trackInfo = await engine.addTrack( cid: track.getCid(), name: track.name, kind: track.kind, + dtx: options?.dtx, ); await track.start(); @@ -73,15 +83,15 @@ class LocalParticipant extends Participant { /// Publish a video track to the room Future publishVideoTrack( LocalVideoTrack track, { - TrackPublishOptions? options, + VideoPublishOptions? options, }) async { if (videoTracks.any( (e) => e.track?.mediaStreamTrack.id == track.mediaStreamTrack.id)) { throw TrackPublishException('track already exists'); } - // Use default options from `ConnectOptions` if options is null - options = options ?? defaultPublishOptions; + // Use defaultPublishOptions if options is null + options = options ?? defaultVideoPublishOptions; final trackInfo = await engine.addTrack( cid: track.getCid(), diff --git a/lib/src/room.dart b/lib/src/room.dart index b83041a..36514b6 100644 --- a/lib/src/room.dart +++ b/lib/src/room.dart @@ -75,7 +75,8 @@ class Room extends DisposableChangeNotifier with EventsEmittable { localParticipant = LocalParticipant( engine: engine, info: joinResponse.participant, - defaultPublishOptions: connectOptions?.defaultPublishOptions, + defaultVideoPublishOptions: connectOptions?.defaultVideoPublishOptions, + defaultAudioPublishOptions: connectOptions?.defaultAudioPublishOptions, roomEvents: events, ); diff --git a/lib/src/rtc_engine.dart b/lib/src/rtc_engine.dart index 6cdee1e..55ef632 100644 --- a/lib/src/rtc_engine.dart +++ b/lib/src/rtc_engine.dart @@ -136,12 +136,18 @@ class RTCEngine extends Disposable with EventsEmittable { required String name, required lk_models.TrackType kind, TrackDimension? dimension, + bool? dtx, }) async { // TODO: Check if cid already published // send request to add track signalClient.sendAddTrack( - cid: cid, name: name, type: kind, dimension: dimension); + cid: cid, + name: name, + type: kind, + dimension: dimension, + dtx: dtx, + ); // wait for response, or timeout final event = await _signalListener.waitFor( diff --git a/lib/src/signal_client.dart b/lib/src/signal_client.dart index 44382c8..eef894b 100644 --- a/lib/src/signal_client.dart +++ b/lib/src/signal_client.dart @@ -155,16 +155,25 @@ class SignalClient extends Disposable with EventsEmittable { required String name, required lk_models.TrackType type, TrackDimension? dimension, + bool? dtx, }) { final req = lk_rtc.AddTrackRequest( cid: cid, name: name, type: type, ); - if (dimension != null) { + + if (type == lk_models.TrackType.VIDEO && dimension != null) { + // video specific req.width = dimension.width; req.height = dimension.height; } + + if (type == lk_models.TrackType.AUDIO && dtx != null) { + // audio specific + req.disableDtx = !dtx; + } + _sendRequest(lk_rtc.SignalRequest( addTrack: req, )); diff --git a/lib/src/utils.dart b/lib/src/utils.dart index d4d65f3..228b75c 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -83,9 +83,9 @@ class Utils { static List? computeVideoEncodings({ int? width, int? height, - TrackPublishOptions? options, + VideoPublishOptions? options, }) { - options ??= const TrackPublishOptions(); + options ??= const VideoPublishOptions(); VideoEncoding? videoEncoding = options.videoEncoding;