feat: 增加分辨率修改

This commit is contained in:
2026-07-21 11:05:40 +08:00
parent 9e5ac91e46
commit 341dce249f
25 changed files with 646 additions and 6 deletions

View File

@@ -11,6 +11,13 @@ import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import java.util.ArrayList;
import java.util.List;
import androidx.appcompat.app.AppCompatActivity;
@@ -47,6 +54,7 @@ public class MainActivity extends AppCompatActivity {
private LinearLayout setupPanel;
private TextView tvStatusControl;
private TextView tvStats;
private Spinner spinnerResolution;
private WebSocketClient wsClient;
private WebRtcClient webRtcClient;
@@ -89,6 +97,7 @@ public class MainActivity extends AppCompatActivity {
setupPanel = findViewById(R.id.setup_panel);
tvStatusControl = findViewById(R.id.tv_status_control);
tvStats = findViewById(R.id.tv_stats);
spinnerResolution = findViewById(R.id.spinner_resolution);
// 默认服务器地址
etServerUrl.setText("ws://175.178.213.60:8088/ws/signal");
@@ -147,6 +156,7 @@ public class MainActivity extends AppCompatActivity {
}
});
setupResolutionSpinner();
updateUI(false);
}
@@ -458,11 +468,64 @@ public class MainActivity extends AppCompatActivity {
tvStatus.setText("状态: 已停止");
}
/** 分辨率预设(发送给被控端的 SET_RESOLUTION 参数)。 */
private static class ResolutionPreset {
final String label;
final int width;
final int height;
final int fps;
ResolutionPreset(String label, int width, int height, int fps) {
this.label = label;
this.width = width;
this.height = height;
this.fps = fps;
}
@Override
public String toString() {
return label;
}
}
/** 构建分辨率下拉框,选择后请求被控端切换采集分辨率。 */
private void setupResolutionSpinner() {
List<ResolutionPreset> presets = new ArrayList<>();
presets.add(new ResolutionPreset("原始画质", 0, 0, 0)); // 被控端原生分辨率
presets.add(new ResolutionPreset("1080P", 1920, 0, 0));
presets.add(new ResolutionPreset("720P", 1280, 0, 0));
presets.add(new ResolutionPreset("480P", 854, 0, 0));
ArrayAdapter<ResolutionPreset> adapter = new ArrayAdapter<>(
this, android.R.layout.simple_spinner_item, presets);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerResolution.setAdapter(adapter);
spinnerResolution.setSelection(0);
// 先选中默认项再设置监听,避免初始化即触发一次切换。
spinnerResolution.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
ResolutionPreset preset = (ResolutionPreset) parent.getItemAtPosition(position);
if (webRtcClient != null) {
webRtcClient.requestResolutionChange(preset.width, preset.height, preset.fps);
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
private void updateUI(boolean connected) {
setupPanel.setVisibility(connected ? View.GONE : View.VISIBLE);
controlPanel.setVisibility(connected ? View.VISIBLE : View.GONE);
btnConnect.setEnabled(!connected);
btnDisconnect.setEnabled(connected);
if (spinnerResolution != null) {
spinnerResolution.setEnabled(connected);
}
if (tvStatusControl != null) {
tvStatusControl.setText(connected ? "远程控制中" : "未连接");
}

View File

@@ -5,6 +5,7 @@ import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.ttstd.control.Action;
import com.ttstd.controller.signaling.SignalMessage;
import com.ttstd.controller.signaling.WebSocketClient;
import com.ttstd.control.ControlMessage;
@@ -239,6 +240,23 @@ public class WebRtcClient {
}
}
/**
* 请求被控端切换屏幕采集分辨率(通过 DataChannel 发送 SET_RESOLUTION 指令)。
* 语义width <= 0 表示被控端原生分辨率height <= 0 时按 width 指定长边依屏幕宽高比缩放;
* fps <= 0 表示沿用当前帧率。
*/
public void requestResolutionChange(int width, int height, int fps) {
if (dataChannel != null && dataChannel.state() == DataChannel.State.OPEN) {
ControlMessage msg = ControlMessage.newBuilder()
.setAction(Action.SET_RESOLUTION)
.setWidth(width)
.setHeight(height)
.setFps(fps)
.build();
sendControlCommand(msg);
}
}
public void close() {
if (remoteVideoTrack != null && remoteSurfaceView != null) {
remoteVideoTrack.removeSink(remoteSurfaceView);

View File

@@ -13,6 +13,8 @@ enum Action {
KEY = 3;
LONG_PRESS = 4;
MOTION_EVENT = 5;
SET_RESOLUTION = 6; // 控制端请求被控端切换屏幕采集分辨率
REPORT_RESOLUTION = 7; // 被控端上报当前实际采集分辨率(含连接建立后的初始值)
}
// 通过 RTCDataChannel 传输的控制指令protobuf 二进制)。
@@ -38,4 +40,12 @@ message ControlMessage {
// 原始动作MOTION_EVENT对应 Android MotionEvent ACTION_*0=DOWN 1=UP 2=MOVE
int32 motion_action = 11;
// 分辨率切换SET_RESOLUTION
// width 为目标长边/宽度;<=0 表示使用被控端原始native分辨率。
// height 为目标高度;<=0 时按被控端屏幕宽高比基于 width 计算(保留原始比例)。
// fps 为目标帧率;<=0 表示沿用当前帧率。
int32 width = 12;
int32 height = 13;
int32 fps = 14;
}

View File

@@ -136,6 +136,13 @@
android:textColor="@android:color/white"
android:textSize="12sp" />
<Spinner
android:id="@+id/spinner_resolution"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:backgroundTint="#80FFFFFF" />
</LinearLayout>
</FrameLayout>