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:
@@ -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]!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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');
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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 ${_}');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ typedef CancelListenFunc = Function();
|
|||||||
enum ProtocolVersion {
|
enum ProtocolVersion {
|
||||||
protocol2,
|
protocol2,
|
||||||
protocol3,
|
protocol3,
|
||||||
|
protocol4,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ConnectionState {
|
enum ConnectionState {
|
||||||
|
|||||||
Reference in New Issue
Block a user