diff --git a/lib/livekit_client.dart b/lib/livekit_client.dart index 6060855..063f9bb 100644 --- a/lib/livekit_client.dart +++ b/lib/livekit_client.dart @@ -23,6 +23,6 @@ export 'src/track/remote/audio.dart'; export 'src/track/remote/remote.dart'; export 'src/track/remote/video.dart'; export 'src/track/track.dart'; -export 'src/types.dart'; +export 'src/types/other.dart'; export 'src/utils.dart'; export 'src/widget/video_track_renderer.dart'; diff --git a/lib/livekit_client_web.dart b/lib/livekit_client_web.dart index 31ceac4..8f9ab4b 100644 --- a/lib/livekit_client_web.dart +++ b/lib/livekit_client_web.dart @@ -1,13 +1,15 @@ import 'dart:async'; + +import 'package:flutter/services.dart'; + +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; + // In order to *not* need this ignore, consider extracting the "web" version // of your plugin as a separate package, instead of inlining it in the same // package as the core of your plugin. // ignore: unused_import -import 'dart:html' as html show document, ScriptElement; - -import 'package:flutter/services.dart'; -import 'package:flutter_web_plugins/flutter_web_plugins.dart'; +import 'dart:html' as html show document, ScriptElement; // import_sorter: keep /// A web implementation of the Livekit plugin. class LiveKitWebPlugin { diff --git a/lib/src/core/engine.dart b/lib/src/core/engine.dart index 6ab4995..bcc4f4f 100644 --- a/lib/src/core/engine.dart +++ b/lib/src/core/engine.dart @@ -1,9 +1,9 @@ import 'dart:async'; -import 'package:collection/collection.dart'; import 'package:flutter/foundation.dart'; + +import 'package:collection/collection.dart'; import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; -import 'package:livekit_client/src/support/websocket.dart'; import 'package:meta/meta.dart'; import '../constants.dart'; @@ -19,7 +19,9 @@ import '../options.dart'; import '../proto/livekit_models.pb.dart' as lk_models; import '../proto/livekit_rtc.pb.dart' as lk_rtc; import '../support/disposable.dart'; -import '../types.dart'; +import '../support/websocket.dart'; +import '../types/other.dart'; +import '../types/video_dimensions.dart'; import '../utils.dart'; import 'room.dart'; import 'signal_client.dart'; diff --git a/lib/src/core/room.dart b/lib/src/core/room.dart index 7c7f96a..5166a26 100644 --- a/lib/src/core/room.dart +++ b/lib/src/core/room.dart @@ -14,7 +14,7 @@ import '../proto/livekit_models.pb.dart' as lk_models; import '../proto/livekit_rtc.pb.dart' as lk_rtc; import '../support/disposable.dart'; import '../track/track.dart'; -import '../types.dart'; +import '../types/other.dart'; import 'engine.dart'; /// Room is the primary construct for LiveKit conferences. It contains a diff --git a/lib/src/core/signal_client.dart b/lib/src/core/signal_client.dart index e16ee42..f888892 100644 --- a/lib/src/core/signal_client.dart +++ b/lib/src/core/signal_client.dart @@ -15,7 +15,8 @@ import '../proto/livekit_models.pb.dart' as lk_models; import '../proto/livekit_rtc.pb.dart' as lk_rtc; import '../support/disposable.dart'; import '../support/websocket.dart'; -import '../types.dart'; +import '../types/other.dart'; +import '../types/video_dimensions.dart'; import '../utils.dart'; class SignalClient extends Disposable with EventsEmittable { diff --git a/lib/src/core/transport.dart b/lib/src/core/transport.dart index efdf43e..1608608 100644 --- a/lib/src/core/transport.dart +++ b/lib/src/core/transport.dart @@ -7,7 +7,7 @@ import '../extensions.dart'; import '../internal/types.dart'; import '../logger.dart'; import '../support/disposable.dart'; -import '../types.dart'; +import '../types/other.dart'; import '../utils.dart'; typedef PCTransportOnOffer = void Function(rtc.RTCSessionDescription offer); diff --git a/lib/src/events.dart b/lib/src/events.dart index 20affd7..efaaed8 100644 --- a/lib/src/events.dart +++ b/lib/src/events.dart @@ -8,7 +8,7 @@ import 'publication/local.dart'; import 'publication/remote.dart'; import 'publication/track_publication.dart'; import 'track/track.dart'; -import 'types.dart'; +import 'types/other.dart'; /// Base type for all LiveKit events. mixin LiveKitEvent {} diff --git a/lib/src/extensions.dart b/lib/src/extensions.dart index 9551c88..2933c97 100644 --- a/lib/src/extensions.dart +++ b/lib/src/extensions.dart @@ -6,7 +6,7 @@ import 'events.dart'; import 'managers/event.dart'; import 'proto/livekit_models.pb.dart' as lk_models; import 'proto/livekit_rtc.pb.dart' as lk_rtc; -import 'types.dart'; +import 'types/other.dart'; extension DataPacketKindExt on lk_models.DataPacket_Kind { Reliability toSDKType() => { diff --git a/lib/src/internal/events.dart b/lib/src/internal/events.dart index 3a123f3..e792840 100644 --- a/lib/src/internal/events.dart +++ b/lib/src/internal/events.dart @@ -5,7 +5,7 @@ import '../events.dart'; import '../proto/livekit_models.pb.dart' as lk_models; import '../proto/livekit_rtc.pb.dart' as lk_rtc; import '../track/track.dart'; -import '../types.dart'; +import '../types/other.dart'; abstract class InternalEvent implements LiveKitEvent {} diff --git a/lib/src/managers/event.dart b/lib/src/managers/event.dart index 80c299d..2586107 100644 --- a/lib/src/managers/event.dart +++ b/lib/src/managers/event.dart @@ -8,7 +8,7 @@ import '../exceptions.dart'; import '../extensions.dart'; import '../logger.dart'; import '../support/disposable.dart'; -import '../types.dart'; +import '../types/other.dart'; mixin EventsEmittable { final events = EventsEmitter(); diff --git a/lib/src/options.dart b/lib/src/options.dart index a402c87..8f2ca71 100644 --- a/lib/src/options.dart +++ b/lib/src/options.dart @@ -4,7 +4,9 @@ import 'track/local/audio.dart'; import 'track/local/video.dart'; import 'track/options.dart'; import 'track/track.dart'; -import 'types.dart'; +import 'types/other.dart'; +import 'types/video_encoding.dart'; +import 'types/video_parameters.dart'; /// Options used when connecting to the server. class ConnectOptions { diff --git a/lib/src/participant/local.dart b/lib/src/participant/local.dart index 746655a..d76fb14 100644 --- a/lib/src/participant/local.dart +++ b/lib/src/participant/local.dart @@ -1,4 +1,5 @@ import 'package:flutter/foundation.dart'; + import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; import 'package:meta/meta.dart'; @@ -15,7 +16,8 @@ import '../publication/local.dart'; import '../track/local/audio.dart'; import '../track/local/local.dart'; import '../track/local/video.dart'; -import '../types.dart'; +import '../types/other.dart'; +import '../types/video_dimensions.dart'; import '../utils.dart'; import 'participant.dart'; diff --git a/lib/src/participant/participant.dart b/lib/src/participant/participant.dart index 0cbbbbc..c6090e7 100644 --- a/lib/src/participant/participant.dart +++ b/lib/src/participant/participant.dart @@ -11,7 +11,7 @@ import '../publication/track_publication.dart'; import '../support/disposable.dart'; import '../track/local/local.dart'; import '../track/track.dart'; -import '../types.dart'; +import '../types/other.dart'; import 'local.dart'; import 'remote.dart'; diff --git a/lib/src/participant/remote.dart b/lib/src/participant/remote.dart index 31e2c6b..07c317d 100644 --- a/lib/src/participant/remote.dart +++ b/lib/src/participant/remote.dart @@ -12,7 +12,7 @@ import '../publication/remote.dart'; import '../track/remote/audio.dart'; import '../track/remote/remote.dart'; import '../track/remote/video.dart'; -import '../types.dart'; +import '../types/other.dart'; import 'participant.dart'; /// Represents other participant in the [Room]. diff --git a/lib/src/publication/remote.dart b/lib/src/publication/remote.dart index 5ac09b9..d654d92 100644 --- a/lib/src/publication/remote.dart +++ b/lib/src/publication/remote.dart @@ -1,8 +1,9 @@ import 'dart:async'; import 'dart:math'; -import 'package:collection/collection.dart'; import 'package:flutter/widgets.dart'; + +import 'package:collection/collection.dart'; import 'package:meta/meta.dart'; import '../core/signal_client.dart'; @@ -16,7 +17,7 @@ import '../proto/livekit_rtc.pb.dart' as lk_rtc; import '../track/local/local.dart'; import '../track/remote/remote.dart'; import '../track/remote/video.dart'; -import '../types.dart'; +import '../types/other.dart'; import '../utils.dart'; import 'track_publication.dart'; diff --git a/lib/src/publication/track_publication.dart b/lib/src/publication/track_publication.dart index 6416dc6..2e2ae03 100644 --- a/lib/src/publication/track_publication.dart +++ b/lib/src/publication/track_publication.dart @@ -1,5 +1,6 @@ import 'package:meta/meta.dart'; +import '../core/signal_client.dart'; import '../events.dart'; import '../extensions.dart'; import '../internal/events.dart'; @@ -7,10 +8,10 @@ import '../logger.dart'; import '../participant/participant.dart'; import '../proto/livekit_models.pb.dart' as lk_models; import '../support/disposable.dart'; -import '../track/track.dart'; import '../track/local/local.dart'; -import '../types.dart'; -import '../core/signal_client.dart'; +import '../track/track.dart'; +import '../types/other.dart'; +import '../types/video_dimensions.dart'; /// Represents a track that's published to the server. This class contains /// metadata associated with tracks. diff --git a/lib/src/support/native.dart b/lib/src/support/native.dart index b2aec5c..8213a8f 100644 --- a/lib/src/support/native.dart +++ b/lib/src/support/native.dart @@ -1,4 +1,5 @@ import 'package:flutter/services.dart'; + import 'package:meta/meta.dart'; import '../logger.dart'; diff --git a/lib/src/track/local/audio.dart b/lib/src/track/local/audio.dart index a8f0805..121b222 100644 --- a/lib/src/track/local/audio.dart +++ b/lib/src/track/local/audio.dart @@ -3,7 +3,7 @@ import 'dart:async'; import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; import '../../proto/livekit_models.pb.dart' as lk_models; -import '../../types.dart'; +import '../../types/other.dart'; import '../audio_management.dart'; import '../options.dart'; import 'local.dart'; diff --git a/lib/src/track/local/local.dart b/lib/src/track/local/local.dart index 827568a..26792de 100644 --- a/lib/src/track/local/local.dart +++ b/lib/src/track/local/local.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; + import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; import 'package:meta/meta.dart'; @@ -8,7 +9,7 @@ import '../../logger.dart'; import '../../participant/remote.dart'; import '../../proto/livekit_models.pb.dart' as lk_models; import '../../support/platform.dart'; -import '../../types.dart'; +import '../../types/other.dart'; import '../options.dart'; import '../remote/audio.dart'; import '../remote/video.dart'; diff --git a/lib/src/track/local/video.dart b/lib/src/track/local/video.dart index 544415e..a6b0819 100644 --- a/lib/src/track/local/video.dart +++ b/lib/src/track/local/video.dart @@ -2,7 +2,7 @@ import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; import '../../logger.dart'; import '../../proto/livekit_models.pb.dart' as lk_models; -import '../../types.dart'; +import '../../types/other.dart'; import '../options.dart'; import '../track.dart'; import 'local.dart'; diff --git a/lib/src/track/options.dart b/lib/src/track/options.dart index 8182b08..f476098 100644 --- a/lib/src/track/options.dart +++ b/lib/src/track/options.dart @@ -1,8 +1,6 @@ -import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; - import '../track/local/audio.dart'; import '../track/local/video.dart'; -import '../types.dart'; +import '../types/video_parameters.dart'; /// A type that represents front or back of the camera. enum CameraPosition { @@ -25,7 +23,7 @@ class CameraCaptureOptions extends VideoCaptureOptions { const CameraCaptureOptions({ this.cameraPosition = CameraPosition.front, - VideoParameters params = VideoParameters.presetQHD169, + VideoParameters params = VideoParametersPresets.h720_169, }) : super(params: params); CameraCaptureOptions.from({required VideoCaptureOptions captureOptions}) @@ -53,7 +51,7 @@ class CameraCaptureOptions extends VideoCaptureOptions { /// Options used when creating a [LocalVideoTrack] that captures the screen. class ScreenShareCaptureOptions extends VideoCaptureOptions { const ScreenShareCaptureOptions({ - VideoParameters params = VideoParameters.presetHD169, + VideoParameters params = VideoParametersPresets.h720_169, }) : super(params: params); ScreenShareCaptureOptions.from({required VideoCaptureOptions captureOptions}) @@ -73,7 +71,7 @@ abstract class VideoCaptureOptions extends LocalTrackOptions { final VideoParameters params; const VideoCaptureOptions({ - this.params = VideoParameters.presetQHD169, + this.params = VideoParametersPresets.h720_169, }); @override @@ -81,414 +79,6 @@ abstract class VideoCaptureOptions extends LocalTrackOptions { params.toMediaConstraintsMap(); } -/// A type that represents video encoding information. -class VideoEncoding { - final int maxFramerate; - final int maxBitrate; - - const VideoEncoding({ - required this.maxFramerate, - required this.maxBitrate, - }); - - @override - String toString() => - '${runtimeType}(maxFramerate: ${maxFramerate}, maxBitrate: ${maxBitrate})'; -} - -/// Convenience extension for [VideoEncoding]. -extension VideoEncodingExt on VideoEncoding { - rtc.RTCRtpEncoding toRTCRtpEncoding({ - String? rid, - double? scaleResolutionDownBy = 1.0, - int? numTemporalLayers, - }) => - rtc.RTCRtpEncoding( - rid: rid, - scaleResolutionDownBy: scaleResolutionDownBy, - maxFramerate: maxFramerate, - maxBitrate: maxBitrate, - numTemporalLayers: numTemporalLayers, - ); -} - -class VideoParameters { - // 16:9 Presets - static const presetH90_169 = VideoParameters( - dimensions: VideoDimensions.h90_169, - encoding: VideoEncoding( - maxBitrate: 60 * 1000, - maxFramerate: 15, - ), - ); - static const presetH180_169 = VideoParameters( - dimensions: VideoDimensions.h180_169, - encoding: VideoEncoding( - maxBitrate: 120 * 1000, - maxFramerate: 15, - ), - ); - - static const presetH216_169 = VideoParameters( - dimensions: VideoDimensions.h216_169, - encoding: VideoEncoding( - maxBitrate: 180 * 1000, - maxFramerate: 15, - ), - ); - - static const presetH360_169 = VideoParameters( - dimensions: VideoDimensions.h360_169, - encoding: VideoEncoding( - maxBitrate: 300 * 1000, - maxFramerate: 20, - ), - ); - - static const presetH540_169 = VideoParameters( - dimensions: VideoDimensions.h540_169, - encoding: VideoEncoding( - maxBitrate: 600 * 1000, - maxFramerate: 25, - ), - ); - - static const presetH720_169 = VideoParameters( - dimensions: VideoDimensions.h720_169, - encoding: VideoEncoding( - maxBitrate: 2 * 1000 * 1000, - maxFramerate: 30, - ), - ); - - static const presetH1080_169 = VideoParameters( - dimensions: VideoDimensions.h1080_169, - encoding: VideoEncoding( - maxBitrate: 3 * 1000 * 1000, - maxFramerate: 30, - ), - ); - - static const presetH1440_169 = VideoParameters( - dimensions: VideoDimensions.h1440_169, - encoding: VideoEncoding( - maxBitrate: 5 * 1000 * 1000, - maxFramerate: 30, - ), - ); - - static const presetH2160_169 = VideoParameters( - dimensions: VideoDimensions.h2160_169, - encoding: VideoEncoding( - maxBitrate: 8 * 1000 * 1000, - maxFramerate: 30, - ), - ); - - // 4:3 presets - - static const presetH120_43 = VideoParameters( - dimensions: VideoDimensions.h120_43, - encoding: VideoEncoding( - maxBitrate: 80 * 1000, - maxFramerate: 15, - ), - ); - - static const presetH180_43 = VideoParameters( - dimensions: VideoDimensions.h180_43, - encoding: VideoEncoding( - maxBitrate: 100 * 1000, - maxFramerate: 15, - ), - ); - - static const presetH240_43 = VideoParameters( - dimensions: VideoDimensions.h240_43, - encoding: VideoEncoding( - maxBitrate: 150 * 1000, - maxFramerate: 15, - ), - ); - - static const presetH360_43 = VideoParameters( - dimensions: VideoDimensions.h360_43, - encoding: VideoEncoding( - maxBitrate: 225 * 1000, - maxFramerate: 20, - ), - ); - - static const presetH480_43 = VideoParameters( - dimensions: VideoDimensions.h480_43, - encoding: VideoEncoding( - maxBitrate: 300 * 1000, - maxFramerate: 20, - ), - ); - - static const presetH540_43 = VideoParameters( - dimensions: VideoDimensions.h540_43, - encoding: VideoEncoding( - maxBitrate: 450 * 1000, - maxFramerate: 25, - ), - ); - - static const presetH720_43 = VideoParameters( - dimensions: VideoDimensions.h720_43, - encoding: VideoEncoding( - maxBitrate: 1 * 500 * 1000, - maxFramerate: 30, - ), - ); - - static const presetH1080_43 = VideoParameters( - dimensions: VideoDimensions.h1080_43, - encoding: VideoEncoding( - maxBitrate: 2 * 500 * 1000, - maxFramerate: 30, - ), - ); - - static const presetH1440_43 = VideoParameters( - dimensions: VideoDimensions.h1440_43, - encoding: VideoEncoding( - maxBitrate: 3 * 500 * 1000, - maxFramerate: 30, - ), - ); - - // Screen share - - static const presetScreenShareH360FPS3 = VideoParameters( - dimensions: VideoDimensions.h360_169, - encoding: VideoEncoding( - maxBitrate: 200 * 1000, - maxFramerate: 3, - ), - ); - - static const presetScreenShareH720FPS5 = VideoParameters( - dimensions: VideoDimensions.h720_169, - encoding: VideoEncoding( - maxBitrate: 400 * 1000, - maxFramerate: 5, - ), - ); - - static const presetScreenShareH720FPS15 = VideoParameters( - dimensions: VideoDimensions.h720_169, - encoding: VideoEncoding( - maxBitrate: 1 * 1000 * 1000, - maxFramerate: 15, - ), - ); - - static const presetScreenShareH1080FPS15 = VideoParameters( - dimensions: VideoDimensions.h1080_169, - encoding: VideoEncoding( - maxBitrate: 1 * 500 * 1000, - maxFramerate: 15, - ), - ); - - static const presetScreenShareH1080FPS30 = VideoParameters( - dimensions: VideoDimensions.h1080_169, - encoding: VideoEncoding( - maxBitrate: 3 * 1000 * 1000, - maxFramerate: 30, - ), - ); - - final String? description; - final VideoDimensions dimensions; - final VideoEncoding encoding; - - const VideoParameters({ - this.description, - required this.dimensions, - required this.encoding, - }); - - static const presetQVGA169 = VideoParameters( - description: 'QVGA(320x180) 16:9', - dimensions: VideoDimensions(320, 180), - encoding: VideoEncoding( - maxBitrate: 120000, - maxFramerate: 10, - ), - ); - - static const presetVGA169 = VideoParameters( - description: 'VGA(640x360) 16:9', - dimensions: VideoDimensions(640, 360), - encoding: VideoEncoding( - maxBitrate: 300000, - maxFramerate: 20, - ), - ); - - static const presetQHD169 = VideoParameters( - description: 'QHD(960x540) 16:9', - dimensions: VideoDimensions(960, 540), - encoding: VideoEncoding( - maxBitrate: 600000, - maxFramerate: 25, - ), - ); - - static const presetHD169 = VideoParameters( - description: 'HD(1280x720) 16:9', - dimensions: VideoDimensions(1280, 720), - encoding: VideoEncoding( - maxBitrate: 2000000, - maxFramerate: 30, - ), - ); - - static const presetFHD169 = VideoParameters( - description: 'FHD(1920x1080) 16:9', - dimensions: VideoDimensions(1920, 1080), - encoding: VideoEncoding( - maxBitrate: 3000000, - maxFramerate: 30, - ), - ); - - static const presetQVGA43 = VideoParameters( - description: 'QVGA(240x180) 4:3', - dimensions: VideoDimensions(240, 180), - encoding: VideoEncoding( - maxBitrate: 90000, - maxFramerate: 10, - ), - ); - - static const presetVGA43 = VideoParameters( - description: 'VGA(480x360) 4:3', - dimensions: VideoDimensions(480, 360), - encoding: VideoEncoding( - maxBitrate: 225000, - maxFramerate: 20, - ), - ); - - static const presetQHD43 = VideoParameters( - description: 'QHD(720x540) 4:3', - dimensions: VideoDimensions(720, 540), - encoding: VideoEncoding( - maxBitrate: 450000, - maxFramerate: 25, - ), - ); - - static const presetHD43 = VideoParameters( - description: 'HD(960x720) 4:3', - dimensions: VideoDimensions(960, 720), - encoding: VideoEncoding( - maxBitrate: 1500000, - maxFramerate: 30, - ), - ); - - static const presetFHD43 = VideoParameters( - description: 'FHD(1440x1080) 4:3', - dimensions: VideoDimensions(1440, 1080), - encoding: VideoEncoding( - maxBitrate: 2800000, - maxFramerate: 30, - ), - ); - - static const presetScreenShareVGA = VideoParameters( - description: 'ScreenShareVGA(640x360)', - dimensions: VideoDimensions(640, 360), - encoding: VideoEncoding( - maxBitrate: 200000, - maxFramerate: 3, - ), - ); - - static const presetScreenShareHD5 = VideoParameters( - description: 'ScreenShareHD5(1280x720)', - dimensions: VideoDimensions(1280, 720), - encoding: VideoEncoding( - maxBitrate: 400000, - maxFramerate: 5, - ), - ); - - static const presetScreenShareHD15 = VideoParameters( - description: 'ScreenShareHD15(1280x720)', - dimensions: VideoDimensions(1280, 720), - encoding: VideoEncoding( - maxBitrate: 1000000, - maxFramerate: 15, - ), - ); - - static const presetScreenShareFHD15 = VideoParameters( - description: 'ScreenShareFHD15(1920x1080)', - dimensions: VideoDimensions(1920, 1080), - encoding: VideoEncoding( - maxBitrate: 1500000, - maxFramerate: 15, - ), - ); - - static const presetScreenShareFHD30 = VideoParameters( - description: 'ScreenShareFHD30(1920x1080)', - dimensions: VideoDimensions(1920, 1080), - encoding: VideoEncoding( - maxBitrate: 3000000, - maxFramerate: 30, - ), - ); - - static final List presets169 = [ - presetH90_169, - presetH180_169, - presetH216_169, - presetH360_169, - presetH540_169, - presetH720_169, - presetH1080_169, - presetH1440_169, - presetH2160_169, - ]; - - static final List presets43 = [ - presetH120_43, - presetH180_43, - presetH240_43, - presetH360_43, - presetH480_43, - presetH540_43, - presetH720_43, - presetH1080_43, - presetH1440_43, - ]; - - static final List presetsScreenShare = [ - presetScreenShareH360FPS3, - presetScreenShareH720FPS5, - presetScreenShareH720FPS15, - presetScreenShareH1080FPS15, - presetScreenShareH1080FPS30, - ]; - - // - // TODO: Return constraints that will work for all platforms (Web & Mobile) - // https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia - // - Map toMediaConstraintsMap() => { - 'width': dimensions.width, - 'height': dimensions.height, - 'frameRate': encoding.maxFramerate, - }; -} - /// Options used when creating a [LocalAudioTrack]. class AudioCaptureOptions extends LocalTrackOptions { /// Attempt to use noiseSuppression option (if supported by the platform) diff --git a/lib/src/track/remote/audio.dart b/lib/src/track/remote/audio.dart index 876925d..c8b7b58 100644 --- a/lib/src/track/remote/audio.dart +++ b/lib/src/track/remote/audio.dart @@ -1,7 +1,7 @@ import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; import '../../proto/livekit_models.pb.dart' as lk_models; -import '../../types.dart'; +import '../../types/other.dart'; import '../audio_management.dart'; import '../local/local.dart'; import 'remote.dart'; diff --git a/lib/src/track/remote/remote.dart b/lib/src/track/remote/remote.dart index 5c40f4d..f2ff548 100644 --- a/lib/src/track/remote/remote.dart +++ b/lib/src/track/remote/remote.dart @@ -1,7 +1,7 @@ import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; import '../../proto/livekit_models.pb.dart' as lk_models; -import '../../types.dart'; +import '../../types/other.dart'; import '../track.dart'; abstract class RemoteTrack extends Track { diff --git a/lib/src/track/remote/video.dart b/lib/src/track/remote/video.dart index c4503d4..cb81ced 100644 --- a/lib/src/track/remote/video.dart +++ b/lib/src/track/remote/video.dart @@ -1,7 +1,7 @@ import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; import '../../proto/livekit_models.pb.dart' as lk_models; -import '../../types.dart'; +import '../../types/other.dart'; import '../local/local.dart'; import 'remote.dart'; diff --git a/lib/src/track/track.dart b/lib/src/track/track.dart index 76a8672..f737e16 100644 --- a/lib/src/track/track.dart +++ b/lib/src/track/track.dart @@ -9,7 +9,7 @@ import '../logger.dart'; import '../managers/event.dart'; import '../proto/livekit_models.pb.dart' as lk_models; import '../support/disposable.dart'; -import '../types.dart'; +import '../types/other.dart'; /// Wrapper around a MediaStreamTrack with additional metadata. /// Base for [AudioTrack] and [VideoTrack], diff --git a/lib/src/track/web/_audio_html.dart b/lib/src/track/web/_audio_html.dart index 5117985..2a7f1be 100644 --- a/lib/src/track/web/_audio_html.dart +++ b/lib/src/track/web/_audio_html.dart @@ -1,11 +1,10 @@ -// ignore: avoid_web_libraries_in_flutter - import 'dart:html' as html; -// ignore: implementation_imports -import 'package:dart_webrtc/src/media_stream_track_impl.dart'; import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; +// ignore: implementation_imports +import 'package:dart_webrtc/src/media_stream_track_impl.dart'; // import_sorter: keep + const audioContainerId = 'livekit_audio_container'; const audioPrefix = 'livekit_audio_'; diff --git a/lib/src/types.dart b/lib/src/types/other.dart similarity index 68% rename from lib/src/types.dart rename to lib/src/types/other.dart index ede1817..4d81362 100644 --- a/lib/src/types.dart +++ b/lib/src/types/other.dart @@ -2,8 +2,8 @@ import 'dart:math' as math; import 'package:flutter/material.dart'; -import 'extensions.dart'; -import 'participant/participant.dart'; +import '../extensions.dart'; +import '../participant/participant.dart'; typedef CancelListenFunc = Function(); @@ -142,58 +142,6 @@ class RTCIceServer { }; } -/// A simple class that represents dimensions of video. -@immutable -class VideoDimensions { - // 16:9 aspect ratio presets - static const h90_169 = VideoDimensions(160, 90); - static const h180_169 = VideoDimensions(320, 180); - static const h216_169 = VideoDimensions(384, 216); - static const h360_169 = VideoDimensions(640, 360); - static const h540_169 = VideoDimensions(960, 540); - static const h720_169 = VideoDimensions(1280, 720); - static const h1080_169 = VideoDimensions(1920, 1080); - static const h1440_169 = VideoDimensions(2560, 1440); - static const h2160_169 = VideoDimensions(3840, 2160); - - // 4:3 aspect ratio presets - static const h120_43 = VideoDimensions(160, 120); - static const h180_43 = VideoDimensions(240, 180); - static const h240_43 = VideoDimensions(320, 240); - static const h360_43 = VideoDimensions(480, 360); - static const h480_43 = VideoDimensions(640, 480); - static const h540_43 = VideoDimensions(720, 540); - static const h720_43 = VideoDimensions(960, 720); - static const h1080_43 = VideoDimensions(1440, 1080); - static const h1440_43 = VideoDimensions(1920, 1440); - - final int width; - final int height; - - const VideoDimensions( - this.width, - this.height, - ); - - @override - String toString() => '${runtimeType}(${width}x${height})'; - - /// Returns the larger value - int max() => math.max(width, height); - - /// Returns the smaller value - int min() => math.min(width, height); - - VideoDimensions copyWith({ - int? width, - int? height, - }) => - VideoDimensions( - width ?? this.width, - height ?? this.height, - ); -} - @immutable class ParticipantTrackPermission { /// The participant id this permission applies to. diff --git a/lib/src/types/video_dimensions.dart b/lib/src/types/video_dimensions.dart new file mode 100644 index 0000000..b168811 --- /dev/null +++ b/lib/src/types/video_dimensions.dart @@ -0,0 +1,62 @@ +import 'dart:math' as math; + +import 'package:meta/meta.dart'; + +/// A simple class that represents dimensions of video. +@immutable +class VideoDimensions { + final int width; + final int height; + + const VideoDimensions( + this.width, + this.height, + ); + + @override + String toString() => '${runtimeType}(${width}x${height})'; + + VideoDimensions copyWith({ + int? width, + int? height, + }) => + VideoDimensions( + width ?? this.width, + height ?? this.height, + ); +} + +extension VideoDimensionsHelpers on VideoDimensions { + /// Returns the larger value + int max() => math.max(width, height); + + /// Returns the smaller value + int min() => math.min(width, height); + + /// Simply returns the area + int area() => width * height; +} + +extension VideoDimensionsPresets on VideoDimensions { + // 16:9 aspect ratio presets + static const h90_169 = VideoDimensions(160, 90); + static const h180_169 = VideoDimensions(320, 180); + static const h216_169 = VideoDimensions(384, 216); + static const h360_169 = VideoDimensions(640, 360); + static const h540_169 = VideoDimensions(960, 540); + static const h720_169 = VideoDimensions(1280, 720); + static const h1080_169 = VideoDimensions(1920, 1080); + static const h1440_169 = VideoDimensions(2560, 1440); + static const h2160_169 = VideoDimensions(3840, 2160); + + // 4:3 aspect ratio presets + static const h120_43 = VideoDimensions(160, 120); + static const h180_43 = VideoDimensions(240, 180); + static const h240_43 = VideoDimensions(320, 240); + static const h360_43 = VideoDimensions(480, 360); + static const h480_43 = VideoDimensions(640, 480); + static const h540_43 = VideoDimensions(720, 540); + static const h720_43 = VideoDimensions(960, 720); + static const h1080_43 = VideoDimensions(1440, 1080); + static const h1440_43 = VideoDimensions(1920, 1440); +} diff --git a/lib/src/types/video_encoding.dart b/lib/src/types/video_encoding.dart new file mode 100644 index 0000000..5a8d507 --- /dev/null +++ b/lib/src/types/video_encoding.dart @@ -0,0 +1,34 @@ +import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; +import 'package:meta/meta.dart'; + +/// A type that represents video encoding information. +@immutable +class VideoEncoding { + final int maxFramerate; + final int maxBitrate; + + const VideoEncoding({ + required this.maxFramerate, + required this.maxBitrate, + }); + + @override + String toString() => + '${runtimeType}(maxFramerate: ${maxFramerate}, maxBitrate: ${maxBitrate})'; +} + +/// Convenience extension for [VideoEncoding]. +extension VideoEncodingExt on VideoEncoding { + rtc.RTCRtpEncoding toRTCRtpEncoding({ + String? rid, + double? scaleResolutionDownBy = 1.0, + int? numTemporalLayers, + }) => + rtc.RTCRtpEncoding( + rid: rid, + scaleResolutionDownBy: scaleResolutionDownBy, + maxFramerate: maxFramerate, + maxBitrate: maxBitrate, + numTemporalLayers: numTemporalLayers, + ); +} diff --git a/lib/src/types/video_parameters.dart b/lib/src/types/video_parameters.dart new file mode 100644 index 0000000..1cfc991 --- /dev/null +++ b/lib/src/types/video_parameters.dart @@ -0,0 +1,258 @@ +import 'package:meta/meta.dart'; + +import 'video_dimensions.dart'; +import 'video_encoding.dart'; + +@immutable +class VideoParameters { + final String? description; + final VideoDimensions dimensions; + final VideoEncoding encoding; + + const VideoParameters({ + this.description, + required this.dimensions, + required this.encoding, + }); + + // + // TODO: Return constraints that will work for all platforms (Web & Mobile) + // https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia + // + Map toMediaConstraintsMap() => { + 'width': dimensions.width, + 'height': dimensions.height, + 'frameRate': encoding.maxFramerate, + }; + + // Comparable + // @override + // int compareTo(VideoParameters other) { + // if (this.dimensions.area() == other.dimensions.area()) { + // return encoding.compare + // } + // } +} + +extension VideoParametersPresets on VideoParameters { + // all 16:9 presets + static final List all169 = [ + h90_169, + h180_169, + h216_169, + h360_169, + h540_169, + h720_169, + h1080_169, + h1440_169, + h2160_169, + ]; + + // all 4:3 presets + static final List all43 = [ + h120_43, + h180_43, + h240_43, + h360_43, + h480_43, + h540_43, + h720_43, + h1080_43, + h1440_43, + ]; + + // all screen share presets + static final List allScreenShare = [ + screenShareH360FPS3, + screenShareH720FPS5, + screenShareH720FPS15, + screenShareH1080FPS15, + screenShareH1080FPS30, + ]; + + // 16:9 Presets + static const h90_169 = VideoParameters( + dimensions: VideoDimensionsPresets.h90_169, + encoding: VideoEncoding( + maxBitrate: 60 * 1000, + maxFramerate: 15, + ), + ); + static const h180_169 = VideoParameters( + dimensions: VideoDimensionsPresets.h180_169, + encoding: VideoEncoding( + maxBitrate: 120 * 1000, + maxFramerate: 15, + ), + ); + + static const h216_169 = VideoParameters( + dimensions: VideoDimensionsPresets.h216_169, + encoding: VideoEncoding( + maxBitrate: 180 * 1000, + maxFramerate: 15, + ), + ); + + static const h360_169 = VideoParameters( + dimensions: VideoDimensionsPresets.h360_169, + encoding: VideoEncoding( + maxBitrate: 300 * 1000, + maxFramerate: 20, + ), + ); + + static const h540_169 = VideoParameters( + dimensions: VideoDimensionsPresets.h540_169, + encoding: VideoEncoding( + maxBitrate: 600 * 1000, + maxFramerate: 25, + ), + ); + + static const h720_169 = VideoParameters( + dimensions: VideoDimensionsPresets.h720_169, + encoding: VideoEncoding( + maxBitrate: 2 * 1000 * 1000, + maxFramerate: 30, + ), + ); + + static const h1080_169 = VideoParameters( + dimensions: VideoDimensionsPresets.h1080_169, + encoding: VideoEncoding( + maxBitrate: 3 * 1000 * 1000, + maxFramerate: 30, + ), + ); + + static const h1440_169 = VideoParameters( + dimensions: VideoDimensionsPresets.h1440_169, + encoding: VideoEncoding( + maxBitrate: 5 * 1000 * 1000, + maxFramerate: 30, + ), + ); + + static const h2160_169 = VideoParameters( + dimensions: VideoDimensionsPresets.h2160_169, + encoding: VideoEncoding( + maxBitrate: 8 * 1000 * 1000, + maxFramerate: 30, + ), + ); + + // 4:3 presets + static const h120_43 = VideoParameters( + dimensions: VideoDimensionsPresets.h120_43, + encoding: VideoEncoding( + maxBitrate: 80 * 1000, + maxFramerate: 15, + ), + ); + + static const h180_43 = VideoParameters( + dimensions: VideoDimensionsPresets.h180_43, + encoding: VideoEncoding( + maxBitrate: 100 * 1000, + maxFramerate: 15, + ), + ); + + static const h240_43 = VideoParameters( + dimensions: VideoDimensionsPresets.h240_43, + encoding: VideoEncoding( + maxBitrate: 150 * 1000, + maxFramerate: 15, + ), + ); + + static const h360_43 = VideoParameters( + dimensions: VideoDimensionsPresets.h360_43, + encoding: VideoEncoding( + maxBitrate: 225 * 1000, + maxFramerate: 20, + ), + ); + + static const h480_43 = VideoParameters( + dimensions: VideoDimensionsPresets.h480_43, + encoding: VideoEncoding( + maxBitrate: 300 * 1000, + maxFramerate: 20, + ), + ); + + static const h540_43 = VideoParameters( + dimensions: VideoDimensionsPresets.h540_43, + encoding: VideoEncoding( + maxBitrate: 450 * 1000, + maxFramerate: 25, + ), + ); + + static const h720_43 = VideoParameters( + dimensions: VideoDimensionsPresets.h720_43, + encoding: VideoEncoding( + maxBitrate: 1 * 500 * 1000, + maxFramerate: 30, + ), + ); + + static const h1080_43 = VideoParameters( + dimensions: VideoDimensionsPresets.h1080_43, + encoding: VideoEncoding( + maxBitrate: 2 * 500 * 1000, + maxFramerate: 30, + ), + ); + + static const h1440_43 = VideoParameters( + dimensions: VideoDimensionsPresets.h1440_43, + encoding: VideoEncoding( + maxBitrate: 3 * 500 * 1000, + maxFramerate: 30, + ), + ); + + // Screen share + static const screenShareH360FPS3 = VideoParameters( + dimensions: VideoDimensionsPresets.h360_169, + encoding: VideoEncoding( + maxBitrate: 200 * 1000, + maxFramerate: 3, + ), + ); + + static const screenShareH720FPS5 = VideoParameters( + dimensions: VideoDimensionsPresets.h720_169, + encoding: VideoEncoding( + maxBitrate: 400 * 1000, + maxFramerate: 5, + ), + ); + + static const screenShareH720FPS15 = VideoParameters( + dimensions: VideoDimensionsPresets.h720_169, + encoding: VideoEncoding( + maxBitrate: 1 * 1000 * 1000, + maxFramerate: 15, + ), + ); + + static const screenShareH1080FPS15 = VideoParameters( + dimensions: VideoDimensionsPresets.h1080_169, + encoding: VideoEncoding( + maxBitrate: 1 * 500 * 1000, + maxFramerate: 15, + ), + ); + + static const screenShareH1080FPS30 = VideoParameters( + dimensions: VideoDimensionsPresets.h1080_169, + encoding: VideoEncoding( + maxBitrate: 3 * 1000 * 1000, + maxFramerate: 30, + ), + ); +} diff --git a/lib/src/utils.dart b/lib/src/utils.dart index 7645927..c1a47ef 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -1,8 +1,9 @@ import 'dart:async'; +import 'package:flutter/foundation.dart'; + import 'package:collection/collection.dart'; import 'package:device_info_plus/device_info_plus.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; import 'package:meta/meta.dart'; @@ -14,7 +15,10 @@ import 'logger.dart'; import 'options.dart'; import 'support/platform.dart'; import 'track/options.dart'; -import 'types.dart'; +import 'types/other.dart'; +import 'types/video_dimensions.dart'; +import 'types/video_encoding.dart'; +import 'types/video_parameters.dart'; extension UriExt on Uri { @internal @@ -189,15 +193,15 @@ class Utils { required bool isScreenShare, required VideoDimensions dimensions, }) { - if (isScreenShare) return VideoParameters.presetsScreenShare; + if (isScreenShare) return VideoParametersPresets.allScreenShare; final double aspect = dimensions.width > dimensions.height ? dimensions.width / dimensions.height : dimensions.height / dimensions.width; if ((aspect - 16.0 / 9.0).abs() < (aspect - 4.0 / 3.0).abs()) { - return VideoParameters.presets169; + return VideoParametersPresets.all169; } - return VideoParameters.presets43; + return VideoParametersPresets.all43; } static VideoEncoding _findAppropriateEncoding({ diff --git a/lib/src/widget/video_track_renderer.dart b/lib/src/widget/video_track_renderer.dart index 2e6f76c..7992f69 100644 --- a/lib/src/widget/video_track_renderer.dart +++ b/lib/src/widget/video_track_renderer.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; + import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; import '../events.dart'; diff --git a/test/core/room_e2e_test.dart b/test/core/room_e2e_test.dart index def7942..73feab5 100644 --- a/test/core/room_e2e_test.dart +++ b/test/core/room_e2e_test.dart @@ -1,7 +1,8 @@ @Timeout(Duration(seconds: 5)) -import 'package:flutter_test/flutter_test.dart'; -import 'package:livekit_client/livekit_client.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:livekit_client/livekit_client.dart'; import '../mock/e2e_container.dart'; import '../mock/test_data.dart'; import '../mock/websocket_mock.dart'; diff --git a/test/core/signal_client_test.dart b/test/core/signal_client_test.dart index 80062b0..22b6980 100644 --- a/test/core/signal_client_test.dart +++ b/test/core/signal_client_test.dart @@ -1,12 +1,13 @@ @Timeout(Duration(seconds: 5)) + import 'package:flutter_test/flutter_test.dart'; +import 'package:protobuf/protobuf.dart'; + import 'package:livekit_client/livekit_client.dart'; import 'package:livekit_client/src/core/signal_client.dart'; import 'package:livekit_client/src/internal/events.dart'; import 'package:livekit_client/src/proto/livekit_models.pb.dart' as lk_models; import 'package:livekit_client/src/proto/livekit_rtc.pb.dart' as lk_rtc; -import 'package:protobuf/protobuf.dart'; - import '../mock/test_data.dart'; import '../mock/websocket_mock.dart'; diff --git a/test/mock/e2e_container.dart b/test/mock/e2e_container.dart index 34bfef3..ea2d2b8 100644 --- a/test/mock/e2e_container.dart +++ b/test/mock/e2e_container.dart @@ -1,7 +1,6 @@ import 'package:livekit_client/livekit_client.dart'; import 'package:livekit_client/src/core/engine.dart'; import 'package:livekit_client/src/core/signal_client.dart'; - import '../core/signal_client_test.dart'; import 'peerconnection_mock.dart'; import 'websocket_mock.dart'; diff --git a/test/mock/e2e_container_test.dart b/test/mock/e2e_container_test.dart index cdf5e54..818a222 100644 --- a/test/mock/e2e_container_test.dart +++ b/test/mock/e2e_container_test.dart @@ -1,7 +1,8 @@ @Timeout(Duration(seconds: 5)) -import 'package:flutter_test/flutter_test.dart'; -import 'package:livekit_client/livekit_client.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:livekit_client/livekit_client.dart'; import '../core/signal_client_test.dart'; import '../mock/e2e_container.dart'; diff --git a/test/utils_test.dart b/test/utils_test.dart index 0603580..306bb91 100644 --- a/test/utils_test.dart +++ b/test/utils_test.dart @@ -1,4 +1,5 @@ import 'package:flutter_test/flutter_test.dart'; + import 'package:livekit_client/src/utils.dart'; void main() {