VideoDimensions instead of width height
This commit is contained in:
@@ -101,8 +101,7 @@ class LocalParticipant extends Participant<LocalTrackPublication> {
|
|||||||
publishOptions ?? room.roomOptions?.defaultVideoPublishOptions;
|
publishOptions ?? room.roomOptions?.defaultVideoPublishOptions;
|
||||||
|
|
||||||
// use constraints passed to getUserMedia by default
|
// use constraints passed to getUserMedia by default
|
||||||
int width = track.currentOptions.params.width;
|
VideoDimensions dimensions = track.currentOptions.params.dimensions;
|
||||||
int height = track.currentOptions.params.height;
|
|
||||||
|
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
// getSettings() is only implemented for Web
|
// getSettings() is only implemented for Web
|
||||||
@@ -110,10 +109,10 @@ class LocalParticipant extends Participant<LocalTrackPublication> {
|
|||||||
// try to use getSettings for more accurate resolution
|
// try to use getSettings for more accurate resolution
|
||||||
final settings = track.mediaStreamTrack.getSettings();
|
final settings = track.mediaStreamTrack.getSettings();
|
||||||
if (settings['width'] is int) {
|
if (settings['width'] is int) {
|
||||||
width = settings['width'] as int;
|
dimensions = dimensions.copyWith(width: settings['width'] as int);
|
||||||
}
|
}
|
||||||
if (settings['height'] is int) {
|
if (settings['height'] is int) {
|
||||||
height = settings['height'] as int;
|
dimensions = dimensions.copyWith(height: settings['height'] as int);
|
||||||
}
|
}
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
logger.warning('Failed to call `mediaStreamTrack.getSettings()`');
|
logger.warning('Failed to call `mediaStreamTrack.getSettings()`');
|
||||||
@@ -125,7 +124,7 @@ class LocalParticipant extends Participant<LocalTrackPublication> {
|
|||||||
name: track.name,
|
name: track.name,
|
||||||
kind: track.kind,
|
kind: track.kind,
|
||||||
source: track.source.toPBType(),
|
source: track.source.toPBType(),
|
||||||
dimension: TrackDimension(width, height),
|
dimensions: dimensions,
|
||||||
);
|
);
|
||||||
|
|
||||||
logger.fine('publishVideoTrack addTrack response: ${trackInfo}');
|
logger.fine('publishVideoTrack addTrack response: ${trackInfo}');
|
||||||
@@ -133,12 +132,11 @@ class LocalParticipant extends Participant<LocalTrackPublication> {
|
|||||||
await track.start();
|
await track.start();
|
||||||
|
|
||||||
logger.fine(
|
logger.fine(
|
||||||
'Compute encodings with resolution: ${width}x${height}, options: ${publishOptions}');
|
'Compute encodings with resolution: ${dimensions}, options: ${publishOptions}');
|
||||||
|
|
||||||
// Video encodings and simulcasts
|
// Video encodings and simulcasts
|
||||||
final encodings = Utils.computeVideoEncodings(
|
final encodings = Utils.computeVideoEncodings(
|
||||||
width: width,
|
dimensions: dimensions,
|
||||||
height: height,
|
|
||||||
options: publishOptions,
|
options: publishOptions,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ abstract class TrackPublication<T extends Track> extends Disposable {
|
|||||||
bool get muted => track?.muted ?? false;
|
bool get muted => track?.muted ?? false;
|
||||||
|
|
||||||
bool simulcasted = false;
|
bool simulcasted = false;
|
||||||
TrackDimension? dimension;
|
VideoDimensions? dimension;
|
||||||
|
|
||||||
bool get subscribed => track != null;
|
bool get subscribed => track != null;
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ abstract class TrackPublication<T extends Track> extends Disposable {
|
|||||||
void updateFromInfo(lk_models.TrackInfo info) {
|
void updateFromInfo(lk_models.TrackInfo info) {
|
||||||
simulcasted = info.simulcast;
|
simulcasted = info.simulcast;
|
||||||
if (info.type == lk_models.TrackType.VIDEO) {
|
if (info.type == lk_models.TrackType.VIDEO) {
|
||||||
dimension = TrackDimension(info.width, info.height);
|
dimension = VideoDimensions(info.width, info.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ class RTCEngine extends Disposable with EventsEmittable<EngineEvent> {
|
|||||||
required String name,
|
required String name,
|
||||||
required lk_models.TrackType kind,
|
required lk_models.TrackType kind,
|
||||||
required lk_models.TrackSource source,
|
required lk_models.TrackSource source,
|
||||||
TrackDimension? dimension,
|
VideoDimensions? dimensions,
|
||||||
bool? dtx,
|
bool? dtx,
|
||||||
}) async {
|
}) async {
|
||||||
// TODO: Check if cid already published
|
// TODO: Check if cid already published
|
||||||
@@ -158,7 +158,7 @@ class RTCEngine extends Disposable with EventsEmittable<EngineEvent> {
|
|||||||
name: name,
|
name: name,
|
||||||
type: kind,
|
type: kind,
|
||||||
source: source,
|
source: source,
|
||||||
dimension: dimension,
|
dimensions: dimensions,
|
||||||
dtx: dtx,
|
dtx: dtx,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ class SignalClient extends Disposable with EventsEmittable<SignalEvent> {
|
|||||||
required String name,
|
required String name,
|
||||||
required lk_models.TrackType type,
|
required lk_models.TrackType type,
|
||||||
required lk_models.TrackSource source,
|
required lk_models.TrackSource source,
|
||||||
TrackDimension? dimension,
|
VideoDimensions? dimensions,
|
||||||
bool? dtx,
|
bool? dtx,
|
||||||
}) {
|
}) {
|
||||||
final req = lk_rtc.AddTrackRequest(
|
final req = lk_rtc.AddTrackRequest(
|
||||||
@@ -158,10 +158,10 @@ class SignalClient extends Disposable with EventsEmittable<SignalEvent> {
|
|||||||
source: source,
|
source: source,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (type == lk_models.TrackType.VIDEO && dimension != null) {
|
if (type == lk_models.TrackType.VIDEO && dimensions != null) {
|
||||||
// video specific
|
// video specific
|
||||||
req.width = dimension.width;
|
req.width = dimensions.width;
|
||||||
req.height = dimension.height;
|
req.height = dimensions.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == lk_models.TrackType.AUDIO && dtx != null) {
|
if (type == lk_models.TrackType.AUDIO && dtx != null) {
|
||||||
|
|||||||
+15
-26
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc;
|
import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc;
|
||||||
import '../track/local/video.dart';
|
import '../track/local/video.dart';
|
||||||
import '../track/local/audio.dart';
|
import '../track/local/audio.dart';
|
||||||
|
import '../types.dart';
|
||||||
|
|
||||||
/// A type that represents front or back of the camera.
|
/// A type that represents front or back of the camera.
|
||||||
enum CameraPosition {
|
enum CameraPosition {
|
||||||
@@ -112,14 +113,12 @@ extension VideoEncodingExt on VideoEncoding {
|
|||||||
|
|
||||||
class VideoParameters {
|
class VideoParameters {
|
||||||
final String description;
|
final String description;
|
||||||
final int width;
|
final VideoDimensions dimensions;
|
||||||
final int height;
|
|
||||||
final VideoEncoding encoding;
|
final VideoEncoding encoding;
|
||||||
|
|
||||||
const VideoParameters({
|
const VideoParameters({
|
||||||
required this.description,
|
required this.description,
|
||||||
required this.width,
|
required this.dimensions,
|
||||||
required this.height,
|
|
||||||
required this.encoding,
|
required this.encoding,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -129,8 +128,7 @@ class VideoParameters {
|
|||||||
|
|
||||||
static const presetQVGA169 = VideoParameters(
|
static const presetQVGA169 = VideoParameters(
|
||||||
description: 'QVGA(320x180) 16:9',
|
description: 'QVGA(320x180) 16:9',
|
||||||
width: 320,
|
dimensions: VideoDimensions(320, 180),
|
||||||
height: 180,
|
|
||||||
encoding: VideoEncoding(
|
encoding: VideoEncoding(
|
||||||
maxBitrate: 125000,
|
maxBitrate: 125000,
|
||||||
maxFramerate: 15,
|
maxFramerate: 15,
|
||||||
@@ -139,8 +137,7 @@ class VideoParameters {
|
|||||||
|
|
||||||
static const presetVGA169 = VideoParameters(
|
static const presetVGA169 = VideoParameters(
|
||||||
description: 'VGA(640x360) 16:9',
|
description: 'VGA(640x360) 16:9',
|
||||||
width: 640,
|
dimensions: VideoDimensions(640, 360),
|
||||||
height: 360,
|
|
||||||
encoding: VideoEncoding(
|
encoding: VideoEncoding(
|
||||||
maxBitrate: 400000,
|
maxBitrate: 400000,
|
||||||
maxFramerate: 30,
|
maxFramerate: 30,
|
||||||
@@ -149,8 +146,7 @@ class VideoParameters {
|
|||||||
|
|
||||||
static const presetQHD169 = VideoParameters(
|
static const presetQHD169 = VideoParameters(
|
||||||
description: 'QHD(960x540) 16:9',
|
description: 'QHD(960x540) 16:9',
|
||||||
width: 960,
|
dimensions: VideoDimensions(960, 540),
|
||||||
height: 540,
|
|
||||||
encoding: VideoEncoding(
|
encoding: VideoEncoding(
|
||||||
maxBitrate: 800000,
|
maxBitrate: 800000,
|
||||||
maxFramerate: 30,
|
maxFramerate: 30,
|
||||||
@@ -159,8 +155,7 @@ class VideoParameters {
|
|||||||
|
|
||||||
static const presetHD169 = VideoParameters(
|
static const presetHD169 = VideoParameters(
|
||||||
description: 'HD(1280x720) 16:9',
|
description: 'HD(1280x720) 16:9',
|
||||||
width: 1280,
|
dimensions: VideoDimensions(1280, 720),
|
||||||
height: 720,
|
|
||||||
encoding: VideoEncoding(
|
encoding: VideoEncoding(
|
||||||
maxBitrate: 2500000,
|
maxBitrate: 2500000,
|
||||||
maxFramerate: 30,
|
maxFramerate: 30,
|
||||||
@@ -169,8 +164,7 @@ class VideoParameters {
|
|||||||
|
|
||||||
static const presetFHD169 = VideoParameters(
|
static const presetFHD169 = VideoParameters(
|
||||||
description: 'FHD(1920x1080) 16:9',
|
description: 'FHD(1920x1080) 16:9',
|
||||||
width: 1920,
|
dimensions: VideoDimensions(1920, 1080),
|
||||||
height: 1080,
|
|
||||||
encoding: VideoEncoding(
|
encoding: VideoEncoding(
|
||||||
maxBitrate: 4000000,
|
maxBitrate: 4000000,
|
||||||
maxFramerate: 30,
|
maxFramerate: 30,
|
||||||
@@ -179,8 +173,7 @@ class VideoParameters {
|
|||||||
|
|
||||||
static const presetQVGA43 = VideoParameters(
|
static const presetQVGA43 = VideoParameters(
|
||||||
description: 'QVGA(240x180) 4:3',
|
description: 'QVGA(240x180) 4:3',
|
||||||
width: 240,
|
dimensions: VideoDimensions(240, 180),
|
||||||
height: 180,
|
|
||||||
encoding: VideoEncoding(
|
encoding: VideoEncoding(
|
||||||
maxBitrate: 100000,
|
maxBitrate: 100000,
|
||||||
maxFramerate: 15,
|
maxFramerate: 15,
|
||||||
@@ -189,8 +182,7 @@ class VideoParameters {
|
|||||||
|
|
||||||
static const presetVGA43 = VideoParameters(
|
static const presetVGA43 = VideoParameters(
|
||||||
description: 'VGA(480x360) 4:3',
|
description: 'VGA(480x360) 4:3',
|
||||||
width: 480,
|
dimensions: VideoDimensions(480, 360),
|
||||||
height: 360,
|
|
||||||
encoding: VideoEncoding(
|
encoding: VideoEncoding(
|
||||||
maxBitrate: 320000,
|
maxBitrate: 320000,
|
||||||
maxFramerate: 30,
|
maxFramerate: 30,
|
||||||
@@ -199,8 +191,7 @@ class VideoParameters {
|
|||||||
|
|
||||||
static const presetQHD43 = VideoParameters(
|
static const presetQHD43 = VideoParameters(
|
||||||
description: 'QHD(720x540) 4:3',
|
description: 'QHD(720x540) 4:3',
|
||||||
width: 720,
|
dimensions: VideoDimensions(720, 540),
|
||||||
height: 540,
|
|
||||||
encoding: VideoEncoding(
|
encoding: VideoEncoding(
|
||||||
maxBitrate: 640000,
|
maxBitrate: 640000,
|
||||||
maxFramerate: 30,
|
maxFramerate: 30,
|
||||||
@@ -209,8 +200,7 @@ class VideoParameters {
|
|||||||
|
|
||||||
static const presetHD43 = VideoParameters(
|
static const presetHD43 = VideoParameters(
|
||||||
description: 'HD(960x720) 4:3',
|
description: 'HD(960x720) 4:3',
|
||||||
width: 960,
|
dimensions: VideoDimensions(960, 720),
|
||||||
height: 720,
|
|
||||||
encoding: VideoEncoding(
|
encoding: VideoEncoding(
|
||||||
maxBitrate: 2000000,
|
maxBitrate: 2000000,
|
||||||
maxFramerate: 30,
|
maxFramerate: 30,
|
||||||
@@ -219,8 +209,7 @@ class VideoParameters {
|
|||||||
|
|
||||||
static const presetFHD43 = VideoParameters(
|
static const presetFHD43 = VideoParameters(
|
||||||
description: 'FHD(1440x1080) 4:3',
|
description: 'FHD(1440x1080) 4:3',
|
||||||
width: 1440,
|
dimensions: VideoDimensions(1440, 1080),
|
||||||
height: 1080,
|
|
||||||
encoding: VideoEncoding(
|
encoding: VideoEncoding(
|
||||||
maxBitrate: 3200000,
|
maxBitrate: 3200000,
|
||||||
maxFramerate: 30,
|
maxFramerate: 30,
|
||||||
@@ -248,8 +237,8 @@ class VideoParameters {
|
|||||||
// https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
|
// https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
|
||||||
//
|
//
|
||||||
Map<String, dynamic> toMediaConstraintsMap() => <String, dynamic>{
|
Map<String, dynamic> toMediaConstraintsMap() => <String, dynamic>{
|
||||||
'width': width,
|
'width': dimensions.width,
|
||||||
'height': height,
|
'height': dimensions.height,
|
||||||
'frameRate': encoding.maxFramerate,
|
'frameRate': encoding.maxFramerate,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-2
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'extensions.dart';
|
import 'extensions.dart';
|
||||||
|
import 'dart:math' as math;
|
||||||
|
|
||||||
typedef CancelListenFunc = Function();
|
typedef CancelListenFunc = Function();
|
||||||
|
|
||||||
@@ -134,12 +135,27 @@ class RTCIceServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@immutable
|
@immutable
|
||||||
class TrackDimension {
|
class VideoDimensions {
|
||||||
final int width;
|
final int width;
|
||||||
final int height;
|
final int height;
|
||||||
|
|
||||||
const TrackDimension(
|
const VideoDimensions(
|
||||||
this.width,
|
this.width,
|
||||||
this.height,
|
this.height,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'VideoDimensions(${width}×${height})';
|
||||||
|
|
||||||
|
/// Returns the larger value
|
||||||
|
int max() => math.max(width, height);
|
||||||
|
|
||||||
|
VideoDimensions copyWith({
|
||||||
|
int? width,
|
||||||
|
int? height,
|
||||||
|
}) =>
|
||||||
|
VideoDimensions(
|
||||||
|
width ?? this.width,
|
||||||
|
height ?? this.height,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-16
@@ -6,6 +6,7 @@ import 'extensions.dart';
|
|||||||
import 'livekit.dart';
|
import 'livekit.dart';
|
||||||
import 'options.dart';
|
import 'options.dart';
|
||||||
import 'track/options.dart';
|
import 'track/options.dart';
|
||||||
|
import 'types.dart';
|
||||||
|
|
||||||
extension UriExt on Uri {
|
extension UriExt on Uri {
|
||||||
bool get isSecureScheme => ['https', 'wss'].contains(scheme);
|
bool get isSecureScheme => ['https', 'wss'].contains(scheme);
|
||||||
@@ -54,53 +55,49 @@ class Utils {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<VideoParameters> _presetsForResolution(
|
static List<VideoParameters> _presetsForDimensions(
|
||||||
int width,
|
VideoDimensions dimensions,
|
||||||
int height,
|
|
||||||
) {
|
) {
|
||||||
final double aspect = width / height;
|
final double aspect = dimensions.width / dimensions.height;
|
||||||
if ((aspect - 16.0 / 9.0).abs() < (aspect - 4.0 / 3.0).abs()) {
|
if ((aspect - 16.0 / 9.0).abs() < (aspect - 4.0 / 3.0).abs()) {
|
||||||
return VideoParameters.presets169;
|
return VideoParameters.presets169;
|
||||||
}
|
}
|
||||||
return VideoParameters.presets43;
|
return VideoParameters.presets43;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VideoParameters _findPresetForResolution(
|
static VideoParameters _findPresetForDimensions(
|
||||||
int width,
|
VideoDimensions dimensions, {
|
||||||
int height, {
|
|
||||||
required List<VideoParameters> presets,
|
required List<VideoParameters> presets,
|
||||||
}) {
|
}) {
|
||||||
assert(presets.isNotEmpty, 'presets should not be empty');
|
assert(presets.isNotEmpty, 'presets should not be empty');
|
||||||
VideoParameters result = presets.first;
|
VideoParameters result = presets.first;
|
||||||
for (final preset in presets) {
|
for (final preset in presets) {
|
||||||
if (width >= preset.width && height >= preset.height) result = preset;
|
if (dimensions.width >= preset.dimensions.width &&
|
||||||
|
dimensions.height >= preset.dimensions.height) result = preset;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<rtc.RTCRtpEncoding>? computeVideoEncodings({
|
static List<rtc.RTCRtpEncoding>? computeVideoEncodings({
|
||||||
int? width,
|
VideoDimensions? dimensions,
|
||||||
int? height,
|
|
||||||
VideoPublishOptions? options,
|
VideoPublishOptions? options,
|
||||||
}) {
|
}) {
|
||||||
options ??= const VideoPublishOptions();
|
options ??= const VideoPublishOptions();
|
||||||
|
|
||||||
VideoEncoding? videoEncoding = options.videoEncoding;
|
VideoEncoding? videoEncoding = options.videoEncoding;
|
||||||
|
|
||||||
if ((videoEncoding == null && !options.simulcast) ||
|
if ((videoEncoding == null && !options.simulcast) || dimensions == null) {
|
||||||
width == null ||
|
|
||||||
height == null) {
|
|
||||||
// don't set encoding when we are not simulcasting and user isn't restricting
|
// don't set encoding when we are not simulcasting and user isn't restricting
|
||||||
// encoding parameters
|
// encoding parameters
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final presets = _presetsForResolution(width, height);
|
final presets = _presetsForDimensions(dimensions);
|
||||||
|
|
||||||
if (videoEncoding == null) {
|
if (videoEncoding == null) {
|
||||||
// find the right encoding based on width/height
|
// find the right encoding based on width/height
|
||||||
final preset = _findPresetForResolution(width, height, presets: presets);
|
final preset = _findPresetForDimensions(dimensions, presets: presets);
|
||||||
// print('Using preset: ${preset.id}');
|
// print('Using preset: ${preset.id}');
|
||||||
videoEncoding = preset.encoding;
|
videoEncoding = preset.encoding;
|
||||||
// log.debug('using video encoding', videoEncoding);
|
// log.debug('using video encoding', videoEncoding);
|
||||||
@@ -118,7 +115,7 @@ class Utils {
|
|||||||
),
|
),
|
||||||
// if resolution is high enough, we would send both h and q res..
|
// if resolution is high enough, we would send both h and q res..
|
||||||
// otherwise only send h
|
// otherwise only send h
|
||||||
if (width >= 960) ...[
|
if (dimensions.max() >= 960) ...[
|
||||||
midPreset.encoding.toRTCRtpEncoding(
|
midPreset.encoding.toRTCRtpEncoding(
|
||||||
rid: 'h',
|
rid: 'h',
|
||||||
// passing decimals to hardware encoder of android devices
|
// passing decimals to hardware encoder of android devices
|
||||||
|
|||||||
Reference in New Issue
Block a user