fix:增加html测试
This commit is contained in:
parent
cd63c0924b
commit
bb682226af
BIN
assets/demo.h264
Normal file
BIN
assets/demo.h264
Normal file
Binary file not shown.
2684
assets/html/h264.html
Normal file
2684
assets/html/h264.html
Normal file
File diff suppressed because it is too large
Load Diff
BIN
assets/talk.h264
Normal file
BIN
assets/talk.h264
Normal file
Binary file not shown.
@ -2,6 +2,7 @@ import 'package:get/get.dart';
|
|||||||
import 'package:star_lock/common/safetyVerification/safetyVerification_binding.dart';
|
import 'package:star_lock/common/safetyVerification/safetyVerification_binding.dart';
|
||||||
import 'package:star_lock/flavors.dart';
|
import 'package:star_lock/flavors.dart';
|
||||||
import 'package:star_lock/login/forgetPassword/starLock_forgetPassword_xhj_page.dart';
|
import 'package:star_lock/login/forgetPassword/starLock_forgetPassword_xhj_page.dart';
|
||||||
|
import 'package:star_lock/login/login/JMuxerApp.dart';
|
||||||
import 'package:star_lock/login/login/starLock_login_xhj_page.dart';
|
import 'package:star_lock/login/login/starLock_login_xhj_page.dart';
|
||||||
import 'package:star_lock/login/register/starLock_register_binding.dart';
|
import 'package:star_lock/login/register/starLock_register_binding.dart';
|
||||||
import 'package:star_lock/login/register/starLock_register_xhj_page.dart';
|
import 'package:star_lock/login/register/starLock_register_xhj_page.dart';
|
||||||
@ -397,6 +398,7 @@ abstract class Routers {
|
|||||||
static const String ownedKeyListPage = '/ownedKeyListPage'; //拥有的钥匙
|
static const String ownedKeyListPage = '/ownedKeyListPage'; //拥有的钥匙
|
||||||
|
|
||||||
static const String starLockLoginPage = '/StarLockLoginPage'; // 登录
|
static const String starLockLoginPage = '/StarLockLoginPage'; // 登录
|
||||||
|
static const String LocalHtmlPage = '/LocalHtmlPage'; // LocalHtmlPage
|
||||||
static const String starLockRegisterPage = '/StarLockRegisterPage'; // 注册
|
static const String starLockRegisterPage = '/StarLockRegisterPage'; // 注册
|
||||||
static const String starLockForgetPasswordPage =
|
static const String starLockForgetPasswordPage =
|
||||||
'/StarLockForgetPasswordPage'; // 忘记密码
|
'/StarLockForgetPasswordPage'; // 忘记密码
|
||||||
@ -638,6 +640,9 @@ abstract class AppRouters {
|
|||||||
page: () => F.sw(
|
page: () => F.sw(
|
||||||
skyCall: () => const StarLockLoginPage(),
|
skyCall: () => const StarLockLoginPage(),
|
||||||
xhjCall: () => const StarLockLoginXHJPage()),
|
xhjCall: () => const StarLockLoginXHJPage()),
|
||||||
|
),GetPage<dynamic>(
|
||||||
|
name: Routers.LocalHtmlPage,
|
||||||
|
page: () => LocalHtmlPage(),
|
||||||
),
|
),
|
||||||
GetPage<dynamic>(
|
GetPage<dynamic>(
|
||||||
name: Routers.starLockRegisterPage,
|
name: Routers.starLockRegisterPage,
|
||||||
|
|||||||
137
lib/login/login/JMuxerApp.dart
Normal file
137
lib/login/login/JMuxerApp.dart
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart' show ByteData, Uint8List, rootBundle;
|
||||||
|
import 'package:webview_flutter/webview_flutter.dart';
|
||||||
|
|
||||||
|
class LocalHtmlPage extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_LocalHtmlPageState createState() => _LocalHtmlPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _LocalHtmlPageState extends State<LocalHtmlPage> {
|
||||||
|
late final WebViewController _controller;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_controller = WebViewController()
|
||||||
|
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||||||
|
..enableZoom(false)
|
||||||
|
..addJavaScriptChannel(
|
||||||
|
'Flutter',
|
||||||
|
onMessageReceived: (message) {
|
||||||
|
print("来自 HTML 的消息: ${message.message}");
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// 加载本地 HTML
|
||||||
|
_loadLocalHtml();
|
||||||
|
_sendFramesToHtml();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _sendFramesToHtml() async {
|
||||||
|
// 读取 assets/demo.h264 文件
|
||||||
|
final ByteData data = await rootBundle.load('assets/talk.h264');
|
||||||
|
final List<int> byteData = data.buffer.asUint8List();
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
int frameSize = 0;
|
||||||
|
|
||||||
|
// 根据 H.264 数据的帧结构来逐帧读取并发送
|
||||||
|
while (offset < byteData.length) {
|
||||||
|
// 获取每一帧的大小
|
||||||
|
frameSize = getFrameSize(byteData, offset);
|
||||||
|
|
||||||
|
if (frameSize == 0) {
|
||||||
|
print("No more frames or error in frame size calculation.");
|
||||||
|
break; // 如果没有更多的帧,或者无法计算帧的大小,则退出循环
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取当前帧数据
|
||||||
|
List<int> frameData = byteData.sublist(offset, offset + frameSize);
|
||||||
|
|
||||||
|
// 将当前帧数据发送到 WebView 中的 feedDataFromFlutter 函数
|
||||||
|
String jsCode = "feedDataFromFlutter(${frameData});";
|
||||||
|
await _controller.runJavaScript(jsCode);
|
||||||
|
|
||||||
|
// 更新偏移量,继续发送下一个帧
|
||||||
|
offset += frameSize;
|
||||||
|
|
||||||
|
// 控制帧率,模拟每秒 22 帧播放(或者根据你的视频帧率调整)
|
||||||
|
await Future.delayed(Duration(milliseconds: (1000 / 22).toInt()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int getFrameSize(List<int> data, int offset) {
|
||||||
|
// 查找第一个 Start Code (0x000001 或 0x00000001)
|
||||||
|
const List<int> startCode1 = [0, 0, 0, 1]; // Start Code: 0x000001
|
||||||
|
const List<int> startCode2 = [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1
|
||||||
|
]; // Start Code: 0x000001 (0x00000001 version)
|
||||||
|
|
||||||
|
// 查找下一个 Start Code 的位置
|
||||||
|
int startCodeStart = -1;
|
||||||
|
int startCodeEnd = -1;
|
||||||
|
for (int i = offset; i < data.length - 3; i++) {
|
||||||
|
// 判断是否匹配 Start Code (0x000001 或 0x00000001)
|
||||||
|
if (_matchesStartCode(data, i, startCode1)) {
|
||||||
|
startCodeStart = i;
|
||||||
|
startCodeEnd = i + startCode1.length;
|
||||||
|
break;
|
||||||
|
} else if (_matchesStartCode(data, i, startCode2)) {
|
||||||
|
startCodeStart = i;
|
||||||
|
startCodeEnd = i + startCode2.length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果找不到有效的 Start Code,返回 0(结束循环)
|
||||||
|
if (startCodeStart == -1) return 0;
|
||||||
|
|
||||||
|
// 查找下一个 Start Code 的位置
|
||||||
|
int nextStartCodeStart = -1;
|
||||||
|
for (int i = startCodeEnd; i < data.length - 3; i++) {
|
||||||
|
if (_matchesStartCode(data, i, startCode1) ||
|
||||||
|
_matchesStartCode(data, i, startCode2)) {
|
||||||
|
nextStartCodeStart = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果找不到下一个 Start Code,说明当前是最后一个 NAL 单元
|
||||||
|
if (nextStartCodeStart == -1) {
|
||||||
|
return data.length - startCodeStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算并返回当前 NAL 单元的大小
|
||||||
|
return nextStartCodeStart - startCodeStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查数据是否匹配 Start Code
|
||||||
|
bool _matchesStartCode(List<int> data, int index, List<int> startCode) {
|
||||||
|
for (int i = 0; i < startCode.length; i++) {
|
||||||
|
if (data[index + i] != startCode[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _loadLocalHtml() async {
|
||||||
|
final String fileHtmlContent =
|
||||||
|
await rootBundle.loadString('assets/html/h264.html');
|
||||||
|
_controller.loadHtmlString(fileHtmlContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text("加载本地 HTML"),
|
||||||
|
),
|
||||||
|
body: WebViewWidget(controller: _controller),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -238,18 +238,23 @@ class _StarLockLoginPageState extends State<StarLockLoginPage> {
|
|||||||
SubmitBtn(
|
SubmitBtn(
|
||||||
btnName: '发送回声测试消息',
|
btnName: '发送回声测试消息',
|
||||||
onClick: () {
|
onClick: () {
|
||||||
StartChartManage().sendEchoMessage(
|
StartChartManage().sendEchoMessage();
|
||||||
ToPeerId: '3phX8Ng2cZHz5NtP8xAf6nYy2z1BYytoejgjoHrWMGhH');
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
SubmitBtn(
|
SubmitBtn(
|
||||||
btnName: '发送对讲请求1',
|
btnName: '发送对讲请求1',
|
||||||
onClick: () {
|
onClick: () {
|
||||||
StartChartManage().sendCallRequestMessage(
|
StartChartManage().sendCallRequestMessage(
|
||||||
ToPeerId: 'CqKJUADeUZsHrSD4SEVnPBr73fbsHNUXCEq9kyCtE3wp',
|
ToPeerId: '3QvLvD3cBnM358bCdccUpGBBYicepEskPXEsh8KvTvY2',
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
SubmitBtn(
|
||||||
|
btnName: '跳转至html',
|
||||||
|
onClick: () {
|
||||||
|
Get.toNamed(Routers.LocalHtmlPage);
|
||||||
|
},
|
||||||
|
),
|
||||||
SizedBox(height: 50.w),
|
SizedBox(height: 50.w),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
|||||||
@ -36,7 +36,6 @@ class UdpTalkAcceptHandler extends ScpMessageBaseHandle
|
|||||||
stopRingtone();
|
stopRingtone();
|
||||||
// 设置状态为接听中
|
// 设置状态为接听中
|
||||||
talkStatus.setDuringCall();
|
talkStatus.setDuringCall();
|
||||||
stopRingtone();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -176,6 +176,7 @@ class StartChartManage {
|
|||||||
|
|
||||||
// 发送上线消息
|
// 发送上线消息
|
||||||
Future<void> _sendOnlineMessage() async {
|
Future<void> _sendOnlineMessage() async {
|
||||||
|
_log(text: '发送上线消息');
|
||||||
if (isOnlineStartChartServer) {
|
if (isOnlineStartChartServer) {
|
||||||
_log(text: '星图已上线,请勿重复发送上线消息');
|
_log(text: '星图已上线,请勿重复发送上线消息');
|
||||||
return;
|
return;
|
||||||
@ -190,6 +191,10 @@ class StartChartManage {
|
|||||||
|
|
||||||
// 发送对讲请求消息
|
// 发送对讲请求消息
|
||||||
Future<void> sendCallRequestMessage({required String ToPeerId}) async {
|
Future<void> sendCallRequestMessage({required String ToPeerId}) async {
|
||||||
|
if (talkStatus.status == TalkStatus.duringCall) {
|
||||||
|
_log(text: '已经在通话中,请勿重复发送对讲请求');
|
||||||
|
return;
|
||||||
|
}
|
||||||
// 组装上线消息
|
// 组装上线消息
|
||||||
final message = MessageCommand.talkRequestMessage(
|
final message = MessageCommand.talkRequestMessage(
|
||||||
FromPeerId: FromPeerId,
|
FromPeerId: FromPeerId,
|
||||||
@ -220,12 +225,13 @@ class StartChartManage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 发送回声测试消息
|
// 发送回声测试消息
|
||||||
void sendEchoMessage({required String ToPeerId}) async {
|
void sendEchoMessage() async {
|
||||||
final message = MessageCommand.echoMessage(
|
final message = MessageCommand.echoMessage(
|
||||||
ToPeerId: ToPeerId,
|
ToPeerId: echoPeerId,
|
||||||
FromPeerId: FromPeerId,
|
FromPeerId: FromPeerId,
|
||||||
);
|
);
|
||||||
await _sendMessage(message: message);
|
await _sendMessage(message: message);
|
||||||
|
_log(text: '发送回声测试消息');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发送网关初始化消息
|
// 发送网关初始化消息
|
||||||
@ -704,7 +710,6 @@ class StartChartManage {
|
|||||||
seconds: talkPingIntervalTime,
|
seconds: talkPingIntervalTime,
|
||||||
),
|
),
|
||||||
(Timer timer) async {
|
(Timer timer) async {
|
||||||
// 重新发送上线消息
|
|
||||||
await sendTalkPingMessage(
|
await sendTalkPingMessage(
|
||||||
ToPeerId: ToPeerId,
|
ToPeerId: ToPeerId,
|
||||||
FromPeerId: FromPeerId,
|
FromPeerId: FromPeerId,
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import 'package:star_lock/talk/startChart/events/talk_status_change_event.dart';
|
|||||||
|
|
||||||
enum TalkStatus {
|
enum TalkStatus {
|
||||||
waitingAnswer, // 等待接听
|
waitingAnswer, // 等待接听
|
||||||
|
waitingData, // 等待数据
|
||||||
duringCall, // 通话中
|
duringCall, // 通话中
|
||||||
rejected, // 被拒绝
|
rejected, // 被拒绝
|
||||||
uninitialized, // 未初始化
|
uninitialized, // 未初始化
|
||||||
|
|||||||
@ -298,6 +298,9 @@ flutter:
|
|||||||
- images/mine/
|
- images/mine/
|
||||||
- images/lockType/
|
- images/lockType/
|
||||||
- assets/
|
- assets/
|
||||||
|
- assets/html/h264.html
|
||||||
|
- assets/demo.h264
|
||||||
|
- assets/talk.h264
|
||||||
- lan/
|
- lan/
|
||||||
# An image asset can refer to one or more resolution-specific "variants", see
|
# An image asset can refer to one or more resolution-specific "variants", see
|
||||||
# https://flutter.dev/assets-and-images/#resolution-aware
|
# https://flutter.dev/assets-and-images/#resolution-aware
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user