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)
This commit is contained in:
Hiroshi Horie
2021-10-26 02:53:34 +09:00
committed by GitHub
parent 71a21f00b6
commit 6240457333
7 changed files with 61 additions and 17 deletions
+1 -1
View File
@@ -79,7 +79,7 @@ class _ConnectPageState extends State<ConnectPage> {
_uriCtrl.text,
_tokenCtrl.text,
options: ConnectOptions(
defaultPublishOptions: TrackPublishOptions(
defaultVideoPublishOptions: VideoPublishOptions(
simulcast: _simulcast,
),
),
+23 -5
View File
@@ -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})';
}
+16 -6
View File
@@ -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<RoomEvent> roomEvents,
}) : super(
info.sid,
@@ -39,16 +42,23 @@ class LocalParticipant extends Participant {
}
/// publish an audio track to the room
Future<TrackPublication> publishAudioTrack(LocalAudioTrack track) async {
Future<TrackPublication> 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<TrackPublication> 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(),
+2 -1
View File
@@ -75,7 +75,8 @@ class Room extends DisposableChangeNotifier with EventsEmittable<RoomEvent> {
localParticipant = LocalParticipant(
engine: engine,
info: joinResponse.participant,
defaultPublishOptions: connectOptions?.defaultPublishOptions,
defaultVideoPublishOptions: connectOptions?.defaultVideoPublishOptions,
defaultAudioPublishOptions: connectOptions?.defaultAudioPublishOptions,
roomEvents: events,
);
+7 -1
View File
@@ -136,12 +136,18 @@ class RTCEngine extends Disposable with EventsEmittable<EngineEvent> {
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<SignalLocalTrackPublishedEvent>(
+10 -1
View File
@@ -155,16 +155,25 @@ class SignalClient extends Disposable with EventsEmittable<SignalEvent> {
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,
));
+2 -2
View File
@@ -83,9 +83,9 @@ class Utils {
static List<rtc.RTCRtpEncoding>? computeVideoEncodings({
int? width,
int? height,
TrackPublishOptions? options,
VideoPublishOptions? options,
}) {
options ??= const TrackPublishOptions();
options ??= const VideoPublishOptions();
VideoEncoding? videoEncoding = options.videoEncoding;