Skip to content

Commit

Permalink
support sync streams (Protocol V10). (#445)
Browse files Browse the repository at this point in the history
* support sync streams.

* add ProtocolVersion.v10.

* Update options.dart

* update.

* update.

* fix.

* revert changes for logger.

* revert changes.

* changes for firefox only.
  • Loading branch information
cloudwebrtc authored Jan 9, 2024
1 parent 63be320 commit 9a36368
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 18 deletions.
7 changes: 5 additions & 2 deletions example/lib/pages/prejoin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,12 @@ class _PreJoinPageState extends State<PreJoinPage> {
roomOptions: RoomOptions(
adaptiveStream: args.adaptiveStream,
dynacast: args.dynacast,
defaultAudioPublishOptions:
const AudioPublishOptions(name: 'custom_audio_track_name'),
defaultAudioPublishOptions: const AudioPublishOptions(
name: 'custom_audio_track_name',
stream: 'custom_sync_stream_id',
),
defaultVideoPublishOptions: VideoPublishOptions(
stream: 'custom_sync_stream_id',
simulcast: args.simulcast,
videoCodec: args.preferredCodec,
backupVideoCodec: BackupVideoCodec(
Expand Down
4 changes: 3 additions & 1 deletion lib/src/core/engine.dart
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ class Engine extends Disposable with EventsEmittable<EngineEvent> {
Iterable<lk_rtc.SimulcastCodec>? simulcastCodecs,
String? sid,
String? videoCodec,
String? stream,
}) async {
// TODO: Check if cid already published

Expand Down Expand Up @@ -275,6 +276,7 @@ class Engine extends Disposable with EventsEmittable<EngineEvent> {
encryptionType: encryptionType,
simulcastCodecs: simulcastCodecs,
sid: sid,
stream: stream,
);

// wait for response, or timeout
Expand Down Expand Up @@ -954,7 +956,7 @@ class Engine extends Disposable with EventsEmittable<EngineEvent> {
return;
}
logger.fine('received answer (type: ${event.sd.type})');
logger.fine('sdp: ${event.sd.sdp}');
logger.finer('sdp: ${event.sd.sdp}');
await publisher!.setRemoteDescription(event.sd);
})
..on<SignalTrickleEvent>((event) async {
Expand Down
15 changes: 13 additions & 2 deletions lib/src/core/room.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import '../track/local/audio.dart';
import '../track/local/video.dart';
import '../track/track.dart';
import '../types/other.dart';
import '../utils.dart';
import 'engine.dart';

import '../track/web/_audio_api.dart'
Expand Down Expand Up @@ -437,9 +438,19 @@ class Room extends DisposableChangeNotifier with EventsEmittable<RoomEvent> {
..on<EngineTrackAddedEvent>((event) async {
logger.fine('EngineTrackAddedEvent trackSid:${event.track.id}');

final idParts = event.stream.id.split('|');
final idParts = unpackStreamId(event.stream.id);
final participantSid = idParts[0];
final trackSid = idParts.elementAtOrNull(1) ?? event.track.id;
var streamId = idParts[1];
var trackSid = event.track.id;

if (kIsWeb && lkBrowser() == BrowserType.firefox) {
// firefox will get streamId (pID|trackId) instead of (pID|streamId) as it doesn't support sync tracks by stream
// and generates its own track id instead of infer from sdp track id.
if (streamId.isNotEmpty && streamId.startsWith('TR')) {
trackSid = streamId;
}
}

final participant = _getRemoteParticipantBySid(participantSid);
try {
if (trackSid == null || trackSid.isEmpty) {
Expand Down
2 changes: 2 additions & 0 deletions lib/src/core/signal_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ extension SignalClientRequests on SignalClient {
Iterable<lk_models.VideoLayer>? videoLayers,
Iterable<lk_rtc.SimulcastCodec>? simulcastCodecs,
String? sid,
String? stream,
}) {
final req = lk_rtc.AddTrackRequest(
cid: cid,
Expand All @@ -448,6 +449,7 @@ extension SignalClientRequests on SignalClient {
simulcastCodecs: simulcastCodecs,
sid: sid,
muted: false,
stream: stream,
);

if (type == lk_models.TrackType.VIDEO) {
Expand Down
4 changes: 2 additions & 2 deletions lib/src/core/transport.dart
Original file line number Diff line number Diff line change
Expand Up @@ -331,8 +331,8 @@ class Transport extends Disposable {
final originalSdp = sd.sdp;
sd.sdp = munged;
try {
logger.fine(
'setting munged ${remote == true ? 'remote' : 'local'} description munged: $munged ');
logger.fine('setting munged ${remote == true ? 'remote' : 'local'}');
logger.finer('description munged: $munged ');
if (remote == true) {
await pc.setRemoteDescription(sd);
} else {
Expand Down
1 change: 1 addition & 0 deletions lib/src/extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ extension ProtocolVersionExt on ProtocolVersion {
ProtocolVersion.v7: '7',
ProtocolVersion.v8: '8',
ProtocolVersion.v9: '9',
ProtocolVersion.v10: '10',
}[this]!;
}

Expand Down
53 changes: 42 additions & 11 deletions lib/src/options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class ConnectOptions {
const ConnectOptions({
this.autoSubscribe = true,
this.rtcConfiguration = const RTCConfiguration(),
this.protocolVersion = ProtocolVersion.v9,
this.protocolVersion = ProtocolVersion.v10,
this.timeouts = Timeouts.defaultTimeouts,
});
}
Expand Down Expand Up @@ -189,8 +189,23 @@ class BackupVideoCodec {
}
}

class PublishOptions {
/// Name of the track.
final String? name;

/// Set stream name for the track. Audio and video tracks with the same stream name
/// will be placed in the same `MediaStream` and offer better synchronization.
/// By default, camera and microphone will be placed in a stream; as would screen_share and screen_share_audio
final String? stream;

const PublishOptions({
this.name,
this.stream,
});
}

/// Options used when publishing video.
class VideoPublishOptions {
class VideoPublishOptions extends PublishOptions {
static const defaultCameraName = 'camera';
static const defaultScreenShareName = 'screenshare';
static const defualtBackupVideoCodec = BackupVideoCodec(
Expand All @@ -212,9 +227,6 @@ class VideoPublishOptions {
/// Defaults to true.
final bool simulcast;

/// Name of the video track.
final String? name;

final List<VideoParameters> videoSimulcastLayers;

final List<VideoParameters> screenShareSimulcastLayers;
Expand All @@ -224,13 +236,14 @@ class VideoPublishOptions {
final BackupVideoCodec backupVideoCodec;

const VideoPublishOptions({
super.name,
super.stream,
this.videoCodec = defaultVideoCodec,
this.videoEncoding,
this.simulcast = true,
this.videoSimulcastLayers = const [],
this.screenShareSimulcastLayers = const [],
this.backupVideoCodec = defualtBackupVideoCodec,
this.name,
this.scalabilityMode,
});

Expand All @@ -242,6 +255,8 @@ class VideoPublishOptions {
String? videoCodec,
BackupVideoCodec? backupVideoCodec,
String? scalabilityMode,
String? name,
String? stream,
}) =>
VideoPublishOptions(
videoEncoding: videoEncoding ?? this.videoEncoding,
Expand All @@ -252,6 +267,8 @@ class VideoPublishOptions {
videoCodec: videoCodec ?? this.videoCodec,
backupVideoCodec: backupVideoCodec ?? this.backupVideoCodec,
scalabilityMode: scalabilityMode ?? this.scalabilityMode,
name: name ?? this.name,
stream: stream ?? this.stream,
);

@override
Expand All @@ -269,7 +286,7 @@ class AudioPreset {
}

/// Options used when publishing audio.
class AudioPublishOptions {
class AudioPublishOptions extends PublishOptions {
static const defaultMicrophoneName = 'microphone';

/// Whether to enable DTX (Discontinuous Transmission) or not.
Expand All @@ -280,11 +297,25 @@ class AudioPublishOptions {
/// max audio bitrate
final int audioBitrate;

/// Name of the audio track.
final String? name;
const AudioPublishOptions({
super.name,
super.stream,
this.dtx = true,
this.audioBitrate = AudioPreset.music,
});

const AudioPublishOptions(
{this.dtx = true, this.audioBitrate = AudioPreset.music, this.name});
AudioPublishOptions copyWith({
bool? dtx,
int? audioBitrate,
String? name,
String? stream,
}) =>
AudioPublishOptions(
dtx: dtx ?? this.dtx,
audioBitrate: audioBitrate ?? this.audioBitrate,
name: name ?? this.name,
stream: stream ?? this.stream,
);

@override
String toString() => '${runtimeType}(dtx: ${dtx})';
Expand Down
3 changes: 3 additions & 0 deletions lib/src/participant/local.dart
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class LocalParticipant extends Participant<LocalTrackPublication> {
final trackInfo = await room.engine.addTrack(
cid: track.getCid(),
name: publishOptions.name ?? AudioPublishOptions.defaultMicrophoneName,
stream: publishOptions.stream,
kind: track.kind.toPBType(),
source: track.source.toPBType(),
dtx: publishOptions.dtx,
Expand Down Expand Up @@ -230,6 +231,7 @@ class LocalParticipant extends Participant<LocalTrackPublication> {
(track.source == TrackSource.screenShareVideo
? VideoPublishOptions.defaultScreenShareName
: VideoPublishOptions.defaultCameraName),
stream: publishOptions.stream,
kind: track.kind.toPBType(),
source: track.source.toPBType(),
dimensions: dimensions,
Expand Down Expand Up @@ -707,6 +709,7 @@ class LocalParticipant extends Participant<LocalTrackPublication> {
(track.source == TrackSource.screenShareVideo
? VideoPublishOptions.defaultScreenShareName
: VideoPublishOptions.defaultCameraName),
stream: options.stream,
kind: track.kind.toPBType(),
source: track.source.toPBType(),
dimensions: dimensions,
Expand Down
1 change: 1 addition & 0 deletions lib/src/types/other.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ enum ProtocolVersion {
v7, // Remote unpublish
v8,
v9,
v10,
}

/// Connection state type used throughout the SDK.
Expand Down
9 changes: 9 additions & 0 deletions lib/src/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -633,3 +633,12 @@ String mimeTypeToVideoCodecString(String mimeType) {
}

const defaultVideoCodec = 'vp8';
const separator = '|';

List<String> unpackStreamId(String packed) {
final parts = packed.split(separator);
if (parts.length > 1) {
return [parts[0], packed.substring(parts[0].length + 1)];
}
return [packed, ''];
}

0 comments on commit 9a36368

Please sign in to comment.