feat: 增加分辨率修改

This commit is contained in:
2026-07-21 10:45:06 +08:00
parent 9e5ac91e46
commit de88776fb1
25 changed files with 646 additions and 6 deletions

View File

@@ -131,6 +131,11 @@ class RemoteController {
_webRtc?.sendControlCommand(command);
}
/// 请求被控端切换屏幕采集分辨率。
void sendResolutionChange(int width, int height, int fps) {
_webRtc?.sendResolutionChange(width, height, fps);
}
/// 断开连接并释放资源。
Future<void> disconnect() async {
_statsTimer?.cancel();

View File

@@ -47,6 +47,16 @@ class _ControllerHomeState extends State<ControllerHome> {
String _stats = '';
double _videoAspect = 16 / 9;
/// 分辨率预设width 为长边像素0 表示被控端原生分辨率;
/// height 传 0由被控端按屏幕宽高比计算fps 传 0沿用当前帧率
int _selectedResolution = 0;
final List<Map<String, Object>> _resolutionOptions = const [
{'label': '原始', 'width': 0, 'height': 0, 'fps': 0},
{'label': '1080P', 'width': 1920, 'height': 0, 'fps': 0},
{'label': '720P', 'width': 1280, 'height': 0, 'fps': 0},
{'label': '480P', 'width': 854, 'height': 0, 'fps': 0},
];
@override
void initState() {
super.initState();
@@ -320,6 +330,29 @@ class _ControllerHomeState extends State<ControllerHome> {
),
),
),
Positioned(
bottom: 16,
left: 16,
child: CupertinoSegmentedControl<int>(
groupValue: _selectedResolution,
children: <int, Widget>{
for (int i = 0; i < _resolutionOptions.length; i++)
i: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
child: Text(_resolutionOptions[i]['label'] as String),
),
},
onValueChanged: (int idx) {
setState(() => _selectedResolution = idx);
final o = _resolutionOptions[idx];
_controller?.sendResolutionChange(
o['width'] as int,
o['height'] as int,
o['fps'] as int,
);
},
),
),
],
),
);

View File

@@ -36,6 +36,9 @@ class ControlMessage extends $pb.GeneratedMessage {
$core.int? keyCode,
$core.int? keyAction,
$core.int? motionAction,
$core.int? width,
$core.int? height,
$core.int? fps,
}) {
final result = create();
if (action != null) result.action = action;
@@ -49,6 +52,9 @@ class ControlMessage extends $pb.GeneratedMessage {
if (keyCode != null) result.keyCode = keyCode;
if (keyAction != null) result.keyAction = keyAction;
if (motionAction != null) result.motionAction = motionAction;
if (width != null) result.width = width;
if (height != null) result.height = height;
if (fps != null) result.fps = fps;
return result;
}
@@ -77,6 +83,9 @@ class ControlMessage extends $pb.GeneratedMessage {
..aI(9, _omitFieldNames ? '' : 'keyCode')
..aI(10, _omitFieldNames ? '' : 'keyAction')
..aI(11, _omitFieldNames ? '' : 'motionAction')
..aI(12, _omitFieldNames ? '' : 'width')
..aI(13, _omitFieldNames ? '' : 'height')
..aI(14, _omitFieldNames ? '' : 'fps')
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
@@ -201,6 +210,36 @@ class ControlMessage extends $pb.GeneratedMessage {
$core.bool hasMotionAction() => $_has(10);
@$pb.TagNumber(11)
void clearMotionAction() => $_clearField(11);
/// 分辨率切换SET_RESOLUTION目标宽度/长边(<=0 表示原生分辨率)
@$pb.TagNumber(12)
$core.int get width => $_getIZ(11);
@$pb.TagNumber(12)
set width($core.int value) => $_setSignedInt32(11, value);
@$pb.TagNumber(12)
$core.bool hasWidth() => $_has(11);
@$pb.TagNumber(12)
void clearWidth() => $_clearField(12);
/// 分辨率切换SET_RESOLUTION目标高度<=0 时按屏幕宽高比基于 width 计算)
@$pb.TagNumber(13)
$core.int get height => $_getIZ(12);
@$pb.TagNumber(13)
set height($core.int value) => $_setSignedInt32(12, value);
@$pb.TagNumber(13)
$core.bool hasHeight() => $_has(12);
@$pb.TagNumber(13)
void clearHeight() => $_clearField(13);
/// 分辨率切换SET_RESOLUTION目标帧率<=0 表示沿用当前帧率)
@$pb.TagNumber(14)
$core.int get fps => $_getIZ(13);
@$pb.TagNumber(14)
set fps($core.int value) => $_setSignedInt32(13, value);
@$pb.TagNumber(14)
$core.bool hasFps() => $_has(13);
@$pb.TagNumber(14)
void clearFps() => $_clearField(14);
}
const $core.bool _omitFieldNames =

View File

@@ -25,6 +25,10 @@ class Action extends $pb.ProtobufEnum {
Action._(4, _omitEnumNames ? '' : 'LONG_PRESS');
static const Action MOTION_EVENT =
Action._(5, _omitEnumNames ? '' : 'MOTION_EVENT');
static const Action SET_RESOLUTION =
Action._(6, _omitEnumNames ? '' : 'SET_RESOLUTION');
static const Action REPORT_RESOLUTION =
Action._(7, _omitEnumNames ? '' : 'REPORT_RESOLUTION');
static const $core.List<Action> values = <Action>[
ACTION_UNKNOWN,
@@ -33,10 +37,12 @@ class Action extends $pb.ProtobufEnum {
KEY,
LONG_PRESS,
MOTION_EVENT,
SET_RESOLUTION,
REPORT_RESOLUTION,
];
static final $core.List<Action?> _byValue =
$pb.ProtobufEnum.$_initByValueList(values, 5);
$pb.ProtobufEnum.$_initByValueList(values, 7);
static Action? valueOf($core.int value) =>
value < 0 || value >= _byValue.length ? null : _byValue[value];

View File

@@ -56,4 +56,16 @@ class ControlCommands {
x: x,
y: y,
);
/// 分辨率切换指令。
/// [width] 目标长边/宽度(<=0 表示被控端原生分辨率);
/// [height] 目标高度(<=0 时由被控端按屏幕宽高比计算);
/// [fps] 目标帧率(<=0 表示沿用当前帧率)。
static ControlMessage setResolution(int width, int height, int fps) =>
ControlMessage(
action: Action.SET_RESOLUTION,
width: width,
height: height,
fps: fps,
);
}

View File

@@ -5,6 +5,7 @@ import '../config/ice_servers.dart';
import '../models/signal_message.dart';
import '../proto/control_message.pb.dart';
import '../signaling/signaling_client.dart';
import '../utils/control_commands.dart';
/// 封装 WebRTC 连接逻辑(对应 Android 端 WebRtcClient
///
@@ -192,6 +193,11 @@ class WebRtcController {
}
}
/// 请求被控端切换屏幕采集分辨率SET_RESOLUTION 指令)。
void sendResolutionChange(int width, int height, int fps) {
sendControlCommand(ControlCommands.setResolution(width, height, fps));
}
/// 上一次统计采样的字节数与时间戳,用于计算每秒网速。
int _prevBytesReceived = 0;
int _prevBytesSent = 0;