1.新增一键登录

2.视频对讲优化--优化帧选择算法,缓冲区管理优化
This commit is contained in:
sky_min 2025-11-15 17:37:42 +08:00
parent 749b79f2b1
commit dfb368d822
7 changed files with 389 additions and 434 deletions

View File

@ -1,6 +1,7 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:star_lock/flavors.dart'; import 'package:star_lock/flavors.dart';
@ -38,6 +39,10 @@ class _StarLockLoginPageState extends State<StarLockLoginPage> {
super.initState(); super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async { WidgetsBinding.instance.addPostFrameCallback((_) async {
AppFirstEnterHandle().getAppFirstEnter(isAgreePrivacy); AppFirstEnterHandle().getAppFirstEnter(isAgreePrivacy);
//
if (state.isChinaUser.value) {
// state.getPhoneNumber();
}
}); });
// StartChartManage().init(); // StartChartManage().init();
} }
@ -83,193 +88,202 @@ class _StarLockLoginPageState extends State<StarLockLoginPage> {
onTap: () { onTap: () {
FocusScope.of(context).unfocus(); FocusScope.of(context).unfocus();
}, },
child: ListView( child: state.isChinaUser.value ? _buildChinaUser() : _buildForeignUser()
padding: EdgeInsets.only(top: 120.h, left: 40.w, right: 40.w), ),
children: <Widget>[ );
Container( }
padding: EdgeInsets.all(10.w),
child: Center(child: Image.asset('images/icon_main_sky_1024.png', width: 110.w, height: 110.w))), Widget _buildChinaUser() {
SizedBox(height: 50.w), return ListView(
Obx(() => CommonItem( padding: EdgeInsets.only(top: 120.h, left: 40.w, right: 40.w),
leftTitel: '你所在的国家/地区'.tr, children: <Widget>[
rightTitle: '', Container(
isHaveLine: true, padding: EdgeInsets.all(10.w),
isPadding: false, alignment: Alignment.center,
isHaveRightWidget: true, child: Column(children: [
isHaveDirection: true, Image.asset('images/icon_main_sky_1024.png', width: 110.w, height: 110.w),
rightWidget: Text( SizedBox(height: 50.w),
'${state.countryName} +${state.countryCode.value}', Text(state.emailOrPhone.value.isNotEmpty ? state.emailOrPhone.value : '获取手机号中...'),
textAlign: TextAlign.end, SizedBox(height: 50.w),
style: TextStyle(fontSize: 22.sp, color: AppColors.darkGrayTextColor), SubmitBtn(
), btnName: '一键登录',
action: () async { fontSize: 28.sp,
final result = await Get.toNamed(Routers.selectCountryRegionPage); borderRadius: 20.w,
if (result != null) { padding: EdgeInsets.only(top: 25.w, bottom: 25.w),
result as Map<String, dynamic>; onClick: () {
state.countryCode.value = result['code']; if (state.agree.value == false) {
state.countryKey.value = result['countryName']; logic.showToast('请先同意用户协议及隐私政策'.tr);
logic.checkIpAction(); return;
} else {
logic.oneClickLoginAction(context);
} }
}, }),
)), SizedBox(height: 50.w),
LoginInput( _agreentWidget(),
focusNode: logic.state.emailOrPhoneFocusNode, ]))
controller: state.emailOrPhoneController, ]);
onchangeAction: (v) { }
logic.checkNext(state.emailOrPhoneController);
}, Widget _buildForeignUser() {
leftWidget: Padding( return ListView(
padding: EdgeInsets.only(top: 30.w, bottom: 20.w, right: 5.w, left: 5.w), padding: EdgeInsets.only(top: 120.h, left: 40.w, right: 40.w),
child: Image.asset( children: <Widget>[
'images/icon_login_account.png', Container(
width: 36.w, padding: EdgeInsets.all(10.w),
height: 36.w, child: Center(child: Image.asset('images/icon_main_sky_1024.png', width: 110.w, height: 110.w))),
), SizedBox(height: 50.w),
), Obx(() => CommonItem(
hintText: '请输入手机号或者邮箱'.tr, leftTitel: '你所在的国家/地区'.tr,
// keyboardType: TextInputType.number, rightTitle: '',
inputFormatters: <TextInputFormatter>[ isHaveLine: true,
// FilteringTextInputFormatter.allow(RegExp('[0-9]')), isPadding: false,
LengthLimitingTextInputFormatter(30), isHaveRightWidget: true,
FilteringTextInputFormatter.singleLineFormatter isHaveDirection: true,
]), rightWidget: Text(
SizedBox(height: 10.h), '${state.countryName} +${state.countryCode.value}',
LoginInput( textAlign: TextAlign.end,
focusNode: logic.state.pwdFocusNode, style: TextStyle(fontSize: 22.sp, color: AppColors.darkGrayTextColor),
controller: state.pwdController, ),
onchangeAction: (v) { action: () async {
logic.checkNext(state.pwdController); final result = await Get.toNamed(Routers.selectCountryRegionPage);
}, if (result != null) {
isPwd: true, result as Map<String, dynamic>;
// isSuffixIcon: 2, state.countryCode.value = result['code'];
leftWidget: Padding( state.countryKey.value = result['countryName'];
padding: EdgeInsets.only(top: 30.w, bottom: 20.w, right: 5.w, left: 5.w), logic.checkIpAction();
child: Image.asset( }
'images/icon_login_password.png', },
width: 36.w, )),
height: 36.w, LoginInput(
), focusNode: logic.state.emailOrPhoneFocusNode,
), controller: state.emailOrPhoneController,
hintText: '请输入密码'.tr, onchangeAction: (v) {
inputFormatters: <TextInputFormatter>[ logic.checkNext(state.emailOrPhoneController);
LengthLimitingTextInputFormatter(20), },
]), leftWidget: Padding(
// SizedBox(height: 15.h), padding: EdgeInsets.only(top: 30.w, bottom: 20.w, right: 5.w, left: 5.w),
Row( child: Image.asset(
mainAxisAlignment: MainAxisAlignment.start, 'images/icon_login_account.png',
children: <Widget>[ width: 36.w,
Obx(() => GestureDetector( height: 36.w,
onTap: () { ),
state.agree.value = !state.agree.value;
logic.changeAgreeState();
},
child: Container(
// color: Colors.red,
padding: EdgeInsets.only(left: 5.w, top: 20.w, right: 10.w, bottom: 20.h),
child: Image.asset(
state.agree.value ? 'images/icon_round_select.png' : 'images/icon_round_unSelect.png',
width: 35.w,
height: 35.w,
),
))),
// SizedBox(
// width: 5.w,
// ),
Flexible(
child: RichText(
text: TextSpan(
text: '我已阅读并同意'.tr,
style: TextStyle(color: const Color(0xff333333), fontSize: 20.sp),
children: <InlineSpan>[
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: GestureDetector(
child:
Text('${'用户协议'.tr}', style: TextStyle(color: AppColors.mainColor, fontSize: 20.sp)),
onTap: () {
Get.toNamed(Routers.webviewShowPage, arguments: <String, String>{
'url': XSConstantMacro.userAgreementURL,
'title': '用户协议'.tr
});
},
)),
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: GestureDetector(
child:
Text('${'隐私政策'.tr}', style: TextStyle(color: AppColors.mainColor, fontSize: 20.sp)),
onTap: () {
Get.toNamed(Routers.webviewShowPage, arguments: <String, String>{
'url': XSConstantMacro.privacyPolicyURL,
'title': '隐私政策'.tr
});
},
)),
],
)),
)
],
), ),
SizedBox(height: 50.w), hintText: '请输入邮箱'.tr,
Obx(() => SubmitBtn( inputFormatters: <TextInputFormatter>[
btnName: '登录'.tr, LengthLimitingTextInputFormatter(30),
fontSize: 28.sp, FilteringTextInputFormatter.singleLineFormatter
borderRadius: 20.w, ]),
padding: EdgeInsets.only(top: 25.w, bottom: 25.w), SizedBox(height: 10.h),
isDisabled: state.canNext.value, LoginInput(
onClick: state.canNext.value focusNode: logic.state.pwdFocusNode,
? () { controller: state.pwdController,
if (state.agree.value == false) { onchangeAction: (v) {
logic.showToast('请先同意用户协议及隐私政策'.tr); logic.checkNext(state.pwdController);
return; },
} else { isPwd: true,
logic.login(); leftWidget: Padding(
} padding: EdgeInsets.only(top: 30.w, bottom: 20.w, right: 5.w, left: 5.w),
} child: Image.asset(
: null)), 'images/icon_login_password.png',
// SizedBox(height: 20.w), width: 36.w,
// Obx(() => Visibility( height: 36.w,
// visible: state.isCheckVerifyEnable.value, ),
// child: SubmitBtn( ),
// btnName: '一键登录', hintText: '请输入密码'.tr,
// fontSize: 28.sp, inputFormatters: <TextInputFormatter>[
// borderRadius: 20.w, LengthLimitingTextInputFormatter(20),
// padding: EdgeInsets.only(top: 25.w, bottom: 25.w), ]),
// // isDisabled: state.canNext.value, SizedBox(height: 50.w),
// onClick: () { Obx(() => SubmitBtn(
// if (state.agree.value == false) { btnName: '登录'.tr,
// logic.showToast('请先同意用户协议及隐私政策'.tr); fontSize: 28.sp,
// return; borderRadius: 20.w,
// } else { padding: EdgeInsets.only(top: 25.w, bottom: 25.w),
// logic.oneClickLoginAction(); isDisabled: state.canNext.value,
// } onClick: state.canNext.value
// }), ? () {
// )), if (state.agree.value == false) {
SizedBox(height: 50.w), logic.showToast('请先同意用户协议及隐私政策'.tr);
Row( return;
mainAxisAlignment: MainAxisAlignment.center, } else {
children: <Widget>[ logic.login();
GestureDetector( }
child: SizedBox( } : null)),
// width: 150.w, SizedBox(height: 20.w),
height: 50.h, Row(
// color: Colors.red, mainAxisAlignment: MainAxisAlignment.center,
child: Center( children: <Widget>[
child: Text('${'忘记密码'.tr}', style: TextStyle(fontSize: 22.sp, color: AppColors.mainColor)), GestureDetector(
), child: SizedBox(
), // width: 150.w,
onTap: () { height: 50.h,
Navigator.pushNamed(context, Routers.starLockForgetPasswordPage); // color: Colors.red,
}, child: Center(
child: Text('${'忘记密码'.tr}', style: TextStyle(fontSize: 22.sp, color: AppColors.mainColor)),
), ),
], ),
onTap: () {
Navigator.pushNamed(context, Routers.starLockForgetPasswordPage);
},
), ),
], ],
), ),
), ],
); );
} }
Widget _agreentWidget() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Obx(() => GestureDetector(
onTap: () {
state.agree.value = !state.agree.value;
logic.changeAgreeState();
},
child: Container(
// color: Colors.red,
padding: EdgeInsets.only(left: 5.w, top: 20.w, right: 10.w, bottom: 20.h),
child: Image.asset(
state.agree.value ? 'images/icon_round_select.png' : 'images/icon_round_unSelect.png',
width: 35.w,
height: 35.w,
),
))),
RichText(
text: TextSpan(
text: '我已阅读并同意'.tr,
style: TextStyle(color: const Color(0xff333333), fontSize: 20.sp),
children: <InlineSpan>[
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: GestureDetector(
child:
Text('${'用户协议'.tr}', style: TextStyle(color: AppColors.mainColor, fontSize: 20.sp)),
onTap: () {
Get.toNamed(Routers.webviewShowPage, arguments: <String, String>{
'url': XSConstantMacro.userAgreementURL,
'title': '用户协议'.tr
});
},
)),
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: GestureDetector(
child:
Text('${'隐私政策'.tr}', style: TextStyle(color: AppColors.mainColor, fontSize: 20.sp)),
onTap: () {
Get.toNamed(Routers.webviewShowPage, arguments: <String, String>{
'url': XSConstantMacro.privacyPolicyURL,
'title': '隐私政策'.tr
});
},
)),
],
)),
]);
}
Widget loginInput( Widget loginInput(
{TextEditingController? controller, {TextEditingController? controller,
List<TextInputFormatter>? inputFormatters, List<TextInputFormatter>? inputFormatters,

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import '../../app_settings/app_settings.dart';
import '../../tools/jverify_one_click_login.dart';
import '../../translations/current_locale_tool.dart'; import '../../translations/current_locale_tool.dart';
class StarLockLoginState { class StarLockLoginState {
@ -14,6 +15,11 @@ class StarLockLoginState {
RxString countryCode = '86'.obs; RxString countryCode = '86'.obs;
RxString countryKey = '中国'.tr.obs; RxString countryKey = '中国'.tr.obs;
//
final RxBool isChinaUser = false.obs;
//
final RxBool showOneClickLogin = false.obs;
/// ///
String get countryName => countryKey.value.tr; String get countryName => countryKey.value.tr;

View File

@ -689,18 +689,35 @@ class LockDetailLogic extends BaseGetXController {
// //
Future<void> remoteOpenLock() async { Future<void> remoteOpenLock() async {
final catEyeConfig = state.keyInfos.value.lockSetting?.catEyeConfig ?? []; final LockListInfoItemEntity currentKeyInfo = CommonDataManage().currentKeyInfo;
//
if (state.keyInfos.value.lockFeature?.isSupportCatEye == 1 && catEyeConfig[0].catEyeMode == 0) { var lockId = currentKeyInfo.lockId ?? 0;
showToast('猫眼设置为省电模式时无法进行远程开锁,请在猫眼设置中切换为其他模式'.tr); var remoteUnlock = currentKeyInfo.lockSetting?.remoteUnlock ?? 0;
return;
final lockPeerId = StartChartManage().lockPeerId;
final LockListInfoGroupEntity? lockListInfoGroupEntity = await Storage.getLockMainListData();
if (lockListInfoGroupEntity != null) {
lockListInfoGroupEntity!.groupList?.forEach((element) {
final lockList = element.lockList;
if (lockList != null && lockList.length != 0) {
for (var lockInfo in lockList) {
final peerId = lockInfo.network?.peerId;
if (peerId != null && peerId != '') {
if (peerId == lockPeerId) {
lockId = lockInfo.lockId ?? 0;
remoteUnlock = lockInfo.lockSetting?.remoteUnlock ?? 0;
}
}
}
}
});
} }
final LoginEntity entity = await ApiRepository.to.remoteOpenLock( if (remoteUnlock == 1) {
lockId: state.keyInfos.value.lockId.toString(), final LoginEntity entity = await ApiRepository.to.remoteOpenLock(lockId: lockId.toString(), timeOut: 60);
timeOut: 60, if (entity.errorCode!.codeIsSuccessful) {
); showToast('已开锁'.tr);
if (entity.errorCode!.codeIsSuccessful) { StartChartManage().lockListPeerId = [];
showToast('已开锁'.tr); }
} }
} }
@ -849,8 +866,6 @@ class LockDetailLogic extends BaseGetXController {
showToast('设备未配网'.tr); showToast('设备未配网'.tr);
return; return;
} }
//
AudioPlayerManager().disableRingtone();
// //
// PacketLossStatistics().reset(); // PacketLossStatistics().reset();
// id // id

View File

@ -41,20 +41,8 @@ class SelectLockTypeLogic extends BaseGetXController {
if (!Platform.isIOS) { if (!Platform.isIOS) {
final bool locationRequest = await PermissionDialog.request(Permission.location); final bool locationRequest = await PermissionDialog.request(Permission.location);
final bool bluetoothRequest = await PermissionDialog.requestBluetooth(); final bool bluetoothRequest = await PermissionDialog.requestBluetooth();
// if (!bluetoothRequest || !locationRequest) {
final bool storageRequest = await PermissionDialog.request(Permission.storage); return;
bool isHarmonyOS = await checkIfHarmonyOS();
// 鸿
if(isHarmonyOS){
print('鸿蒙手机提示----');
if (!bluetoothRequest || !locationRequest || !storageRequest) {
return;
}
} else {
if (!bluetoothRequest || !locationRequest) {
return;
}
} }
} }

View File

@ -193,34 +193,10 @@ class _MessageListPageState extends State<MessageListPage>
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 30.sp)), fontSize: 30.sp)),
//
// GestureDetector(
// onTap: () {
// // api接口使
// // if (_showCheckboxes.value) {
// // deleteSelectedMessages();
// // } else {
// // setState(() {
// // _showCheckboxes.value =
// // !_showCheckboxes.value;
// // });
// // }
// },
// child: _showCheckboxes.value
// ? Text('删除',
// style: TextStyle(
// fontSize: 24.sp,
// color: Colors.red))
// : Image.asset(
// 'images/mine/icon_message_checbox.png',
// width: 30.w,
// height: 30.h),
// )
]), ]),
) )
]))), ]))),
Container( Container(
child: Container(
padding: EdgeInsets.only( padding: EdgeInsets.only(
top: showNotificationBanner ? 80 : 50), top: showNotificationBanner ? 80 : 50),
child: ListView.builder( child: ListView.builder(
@ -270,7 +246,6 @@ class _MessageListPageState extends State<MessageListPage>
}, },
), ),
), ),
)
], ],
); );
})), })),
@ -342,7 +317,7 @@ class _MessageListPageState extends State<MessageListPage>
if (!isLastInGroupSimple) if (!isLastInGroupSimple)
Container( Container(
width: 0.5, width: 0.5,
height: 190.h, height: 120.h,
color: AppColors.placeholderTextColor, color: AppColors.placeholderTextColor,
) )
], ],
@ -370,7 +345,7 @@ class _MessageListPageState extends State<MessageListPage>
], ],
), child: Container( ), child: Container(
width: 1.sw, width: 1.sw,
margin: EdgeInsets.all(20.h), margin: EdgeInsets.all(10.h),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(10.w), borderRadius: BorderRadius.circular(10.w),
@ -381,42 +356,8 @@ class _MessageListPageState extends State<MessageListPage>
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
// SizedBox(height: 4.h),
// Row(
// children: <Widget>[
// Flexible(
// child: Text(
// //
// '远程开门请求',
// maxLines: 1,
// overflow: TextOverflow.ellipsis,
// style: TextStyle(
// fontSize: 22.sp,
// color: messageItemEntity.readAt! == 0
// ? AppColors.blackColor
// : AppColors.placeholderTextColor),
// ),
// ),
// ],
// ),
// SizedBox(height: 4.h),
Wrap( Wrap(
children: <Widget>[ children: <Widget>[
// if (messageItemEntity.readAt! == 0)
// Container(
// width: 10.w,
// height: 10.w,
// decoration: BoxDecoration(
// color: Colors.red,
// borderRadius: BorderRadius.circular(5.w),
// ),
// )
// else
// Container(),
// if (messageItemEntity.readAt! == 0)
// SizedBox(width: 5.w)
// else
// Container(),
Container( Container(
margin: EdgeInsets.only(top: 4.h), margin: EdgeInsets.only(top: 4.h),
child: Text( child: Text(
@ -437,7 +378,7 @@ class _MessageListPageState extends State<MessageListPage>
? AppColors.blackColor ? AppColors.blackColor
: AppColors.placeholderTextColor, : AppColors.placeholderTextColor,
), ),
Container(transform: Matrix4.translationValues(0, -18, 0), Container(transform: Matrix4.translationValues(0, -22, 0),
child: Text(' ${messageItemEntity.data!}', child: Text(' ${messageItemEntity.data!}',
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
@ -453,24 +394,6 @@ class _MessageListPageState extends State<MessageListPage>
),alignment: Alignment.centerRight,) ),alignment: Alignment.centerRight,)
], ],
), ),
// SizedBox(height: 5.h),
// Row(
// mainAxisAlignment: MainAxisAlignment.start,
// children: <Widget>[
// // Image.asset('images/mine/icon_mine_gatewaySignal_strong.png', width: 40.w, height: 40.w,),
// // SizedBox(width: 10.w,),
// Text(
// DateTool().dateToHnString(messageItemEntity
// .createdAt!
// .toString()),
// style: TextStyle(
// fontSize: 18.sp,
// color: messageItemEntity.readAt! == 0
// ? AppColors.blackColor
// : AppColors.placeholderTextColor)),
// ],
// ),
// SizedBox(width: 20.h),
]))))), ]))))),
// //
if (_showCheckboxes.value) if (_showCheckboxes.value)

View File

@ -41,6 +41,33 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
final LockDetailState lockDetailState = Get.put(LockDetailLogic()).state; final LockDetailState lockDetailState = Get.put(LockDetailLogic()).state;
//
final Map<TalkDataH264Frame_FrameTypeE, List<MapEntry<int, int>>> _frameIndexCache = {};
bool _frameIndexDirty = true;
//
void _invalidateFrameIndex() {
_frameIndexDirty = true;
}
//
List<MapEntry<int, int>> _buildFrameIndex(TalkDataH264Frame_FrameTypeE frameType) {
if (!_frameIndexDirty && _frameIndexCache.containsKey(frameType)) {
return _frameIndexCache[frameType]!;
}
final List<MapEntry<int, int>> index = [];
for (int i = 0; i < state.h264FrameBuffer.length; i++) {
final frame = state.h264FrameBuffer[i];
if (frame['frameType'] == frameType) {
index.add(MapEntry(frame['frameSeq'] as int, i));
}
}
index.sort((a, b) => a.key.compareTo(b.key));
_frameIndexCache[frameType] = index;
_frameIndexDirty = false;
return index;
}
// //
int _networkQualityScore = 5; // 1-55 int _networkQualityScore = 5; // 1-55
int _frameDropCount = 0; int _frameDropCount = 0;
@ -296,7 +323,13 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
VideoDecodePlugin.setOnFrameRenderedListener((textureId) { VideoDecodePlugin.setOnFrameRenderedListener((textureId) {
AppLog.log('已经开始渲染======='); AppLog.log('已经开始渲染=======');
// loading // loading
Future.microtask(() => state.isLoading.value = false); Future.microtask(() {
state.isLoading.value = false;
//
if (state.animationController.isAnimating) {
state.animationController.stop();
}
});
}); });
} else { } else {
AppLog.log('视频解码器初始化失败或超时, 耗时: ${duration}ms'); AppLog.log('视频解码器初始化失败或超时, 耗时: ${duration}ms');
@ -432,6 +465,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
// //
state.h264FrameBuffer.add(frameMap); state.h264FrameBuffer.add(frameMap);
_invalidateFrameIndex();
} }
/// ///
@ -494,11 +528,43 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
} else { } else {
// P帧或B帧 // P帧或B帧
state.h264FrameBuffer.removeAt(0); state.h264FrameBuffer.removeAt(0);
_invalidateFrameIndex();
} }
} }
int _findEarliestIFrame() {
final iFrameIndexes = _buildFrameIndex(TalkDataH264Frame_FrameTypeE.I);
return iFrameIndexes.isNotEmpty ? iFrameIndexes.first.value : -1;
}
int _findRelatedPFrame(int refIFrameSeq) {
final pFrameIndexes = _buildFrameIndex(TalkDataH264Frame_FrameTypeE.P);
for (final entry in pFrameIndexes) {
final frame = state.h264FrameBuffer[entry.value];
if (frame['frameSeqI'] == refIFrameSeq) {
return entry.value;
}
}
return -1;
}
int _findBestFrameIndex() {
// I帧相关的P帧
if (lastDecodedIFrameSeq != null) {
final pFrameIndex = _findRelatedPFrame(lastDecodedIFrameSeq!);
if (pFrameIndex >= 0) return pFrameIndex;
}
// I帧
final iFrameIndex = _findEarliestIFrame();
if (iFrameIndex >= 0) return iFrameIndex;
// I帧
return state.h264FrameBuffer.isNotEmpty ? 0 : -1;
}
/// ///
void _processNextFrameFromBuffer() async { void _processNextFrameFromBuffer() async {
final stopwatch = Stopwatch()..start();
_monitorFrameProcessingPerformance(); _monitorFrameProcessingPerformance();
final startTime = DateTime.now().microsecondsSinceEpoch; final startTime = DateTime.now().microsecondsSinceEpoch;
@ -543,63 +609,8 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
} }
} }
// -- I帧以加速首帧显示 //
int frameIndex = -1; final frameIndex = _findBestFrameIndex();
// I帧
final iFrames = state.h264FrameBuffer
.where((f) => f['frameType'] == TalkDataH264Frame_FrameTypeE.I)
.toList()
..sort((a, b) => (a['frameSeq'] as int).compareTo(b['frameSeq'] as int));
if (iFrames.isNotEmpty) {
final minIFrame = iFrames.first;
frameIndex = state.h264FrameBuffer.indexWhere(
(f) =>
f['frameType'] == TalkDataH264Frame_FrameTypeE.I &&
f['frameSeq'] == minIFrame['frameSeq'],
);
} else {
// I帧
frameIndex = 0;
}
// I帧相关的P帧
if (lastDecodedIFrameSeq != null) {
// I帧关联的P帧
final validPFrames = state.h264FrameBuffer
.where((f) =>
f['frameType'] == TalkDataH264Frame_FrameTypeE.P &&
f['frameSeqI'] == lastDecodedIFrameSeq)
.toList()
..sort((a, b) => (a['frameSeq'] as int).compareTo(b['frameSeq'] as int));
if (validPFrames.isNotEmpty) {
final minPFrame = validPFrames.first;
frameIndex = state.h264FrameBuffer.indexWhere(
(f) =>
f['frameType'] == TalkDataH264Frame_FrameTypeE.P &&
f['frameSeq'] == minPFrame['frameSeq'] &&
f['frameSeqI'] == lastDecodedIFrameSeq,
);
}
}
// P帧I帧
if (frameIndex == -1) {
final iFrames = state.h264FrameBuffer
.where((f) => f['frameType'] == TalkDataH264Frame_FrameTypeE.I)
.toList()
..sort((a, b) => (a['frameSeq'] as int).compareTo(b['frameSeq'] as int));
if (iFrames.isNotEmpty) {
final minIFrame = iFrames.first;
frameIndex = state.h264FrameBuffer.indexWhere(
(f) =>
f['frameType'] == TalkDataH264Frame_FrameTypeE.I &&
f['frameSeq'] == minIFrame['frameSeq'],
);
}
}
// //
if (frameIndex >= 0) { if (frameIndex >= 0) {
@ -657,6 +668,8 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
AppLog.log('帧处理耗时过长: ${durationMs.toStringAsFixed(2)} ms, 缓冲区长度: ${state.h264FrameBuffer.length}'); AppLog.log('帧处理耗时过长: ${durationMs.toStringAsFixed(2)} ms, 缓冲区长度: ${state.h264FrameBuffer.length}');
} }
} }
stopwatch.stop();
print('执行耗时: ${stopwatch.elapsedMilliseconds} 毫秒');
} }

View File

@ -10,21 +10,21 @@ import '../app_settings/app_settings.dart';
import '../common/XSConstantMacro/XSConstantMacro.dart'; import '../common/XSConstantMacro/XSConstantMacro.dart';
import '../flavors.dart'; import '../flavors.dart';
class JverifyOneClickLoginManage { class JverifyOneClickLoginManage {
factory JverifyOneClickLoginManage() => shareManager()!; factory JverifyOneClickLoginManage() => _getInstance()!;
JverifyOneClickLoginManage._init() { JverifyOneClickLoginManage._init() {}
_initSDK();
static JverifyOneClickLoginManage get instance => _getInstance();
static JverifyOneClickLoginManage? _instance;
static JverifyOneClickLoginManage _getInstance() {
_instance ??= JverifyOneClickLoginManage._init();
return _instance!;
} }
static JverifyOneClickLoginManage? _manager; JverifyOneClickLoginManage? get manager => _getInstance();
static JverifyOneClickLoginManage? shareManager() {
_manager ??= JverifyOneClickLoginManage._init();
return _manager;
}
JverifyOneClickLoginManage? get manager => shareManager();
Jverify jverify = Jverify(); Jverify jverify = Jverify();
/// key /// key
@ -39,106 +39,102 @@ class JverifyOneClickLoginManage {
/// ///
String f_opr_key = 'operator'; String f_opr_key = 'operator';
Future<void> _initSDK() async { Future<void> initSDK({Function? onSuccess, Function? onFailure}) async {
try { try {
await initPlatformState(); // SDK
jverify.addSDKSetupCallBackListener((JVSDKSetupEvent event) {
print('receive sdk setup call back event :${event.toMap()}');
if (event.code == 8000) {
onSuccess?.call();
} else {
onFailure?.call();
}
});
isInitSuccess(); jverify.setDebugMode(true); //
jverify.setCollectionAuth(true);
String appKey;
if (F.isSKY) {
appKey = '7ff37d174c1a568a89e98dad';
AppLog.log('appKey:7ff37d174c1a568a89e98dad');
} else {
appKey = '251fc8074820d122b6de58d2';
AppLog.log('appKey:251fc8074820d122b6de58d2');
}
jverify.setup(
appKey: appKey, //"你自己应用的 AppKey",
channel: 'devloper');
getToken(); ///
jverify.addAuthPageEventListener((JVAuthPageEvent event) {
print('receive auth page event :${event.toMap()}');
});
preLogin(); // isInitSuccess();
// getToken();
// preLogin();
} catch (e) { } catch (e) {
AppLog.log('SDK 初始化错误: $e'); AppLog.log('SDK 初始化错误: $e');
} }
} }
Future<void> initPlatformState() async {
// SDK
jverify.addSDKSetupCallBackListener((JVSDKSetupEvent event) {
print('receive sdk setup call back event :${event.toMap()}');
});
jverify.setDebugMode(true); //
jverify.setCollectionAuth(true);
String appKey;
if (F.isSKY) {
appKey = '7ff37d174c1a568a89e98dad';
AppLog.log('appKey:7ff37d174c1a568a89e98dad');
} else {
appKey = '251fc8074820d122b6de58d2';
AppLog.log('appKey:251fc8074820d122b6de58d2');
}
jverify.setup(
appKey: appKey, //"你自己应用的 AppKey",
channel: 'devloper');
///
jverify.addAuthPageEventListener((JVAuthPageEvent event) {
print('receive auth page event :${event.toMap()}');
});
}
/// sdk /// sdk
void isInitSuccess() { Future<bool> isInitSuccess() async {
jverify.isInitSuccess().then((map) { final Map<dynamic, dynamic> map = await jverify.isInitSuccess();
final bool result = map[f_result_key]; final bool result = map[f_result_key];
AppLog.log('sdk 初始化结果:$map'); AppLog.log('sdk 初始化结果:$map');
if (result) { if (result) {
AppLog.log('sdk 初始化成功'); AppLog.log('sdk 初始化成功');
} else { } else {
AppLog.log('sdk 初始化失败'); AppLog.log('sdk 初始化失败');
} }
}); return Future.value(result);
} }
/// ///
Future<bool> checkVerifyEnable() async { Future<bool> checkVerifyEnable() async {
final isInitSuccess = await this.isInitSuccess();
if (!isInitSuccess) {
return false;
}
final Map map = await jverify.checkVerifyEnable(); final Map map = await jverify.checkVerifyEnable();
AppLog.log('一家登录 sdk 初始化结果:$map'); print('一家登录 sdk 初始化结果:$map');
final bool result = map[f_result_key]; final bool result = map[f_result_key];
return result; return result;
// state.jverify.checkVerifyEnable().then((map) {
// final bool result = map[f_result_key];
// if (result) {
// AppLog.log('当前网络环境【支持认证】!');
// } else {
// AppLog.log('当前网络环境【不支持认证】!');
// }
// return result;
// });
} }
void getToken() { // void getToken() {
jverify.checkVerifyEnable().then((map) { // jverify.checkVerifyEnable().then((map) {
final bool result = map[f_result_key]; // final bool result = map[f_result_key];
if (result) { // if (result) {
jverify.getToken().then((map) { // jverify.getToken().then((map) {
final int code = map[f_code_key]; // final int code = map[f_code_key];
final String token = map[f_msg_key]; // final String token = map[f_msg_key];
final String operator = map[f_opr_key]; // final String operator = map[f_opr_key];
AppLog.log('getToken code:$code token:$token operator:$operator'); // AppLog.log('getToken code:$code token:$token operator:$operator');
}); // });
} else { // } else {
AppLog.log('[2016],msg = 当前网络环境不支持认证'); // AppLog.log('[2016],msg = 当前网络环境不支持认证');
} // }
}); // });
} // }
/// ///
void preLogin() { Future<bool> preLogin() async {
jverify.checkVerifyEnable().then((map) { final networkSupportVerify = await this.checkVerifyEnable();
final bool result = map[f_result_key]; if (!networkSupportVerify) {
if (result) { return false;
jverify.preLogin().then((map) { }
AppLog.log('预取号接口回调:${map.toString()}'); final Map map = await jverify.preLogin();
final int code = map[f_code_key]; final int code = map[f_code_key];
final String message = map[f_msg_key]; final String message = map[f_msg_key];
}); if (code > 0) {
} else { return true;
AppLog.log('[2016],msg = 当前网络环境不支持认证'); }
} AppLog.log('[2016],msg = 当前网络环境不支持认证');
}); return false;
} }
/// SDK /// SDK