可视对讲ios首次点击监控没有画面-->视频解码器宽高
This commit is contained in:
parent
4303886a7e
commit
35fd6dae4f
@ -40,9 +40,6 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
||||
int bufferSize = 25; // 初始化为默认大小
|
||||
|
||||
int audioBufferSize = 20; // 音频默认缓冲2帧
|
||||
|
||||
// 添加一个计时器来监听videoWidth和videoHeight的变化
|
||||
Timer? _videoDimensionCheckTimer;
|
||||
|
||||
// 回绕阈值,动态调整,frameSeq较小时阈值也小
|
||||
int _getFrameSeqRolloverThreshold(int lastSeq) {
|
||||
@ -96,17 +93,42 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
||||
Future<void> _initVideoDecoder() async {
|
||||
try {
|
||||
state.isLoading.value = true;
|
||||
|
||||
// ios第一次点击监控没画面
|
||||
// 等待视频参数就绪,设置超时时间
|
||||
int width = StartChartManage().videoWidth;
|
||||
int height = StartChartManage().videoHeight;
|
||||
|
||||
// 等待videoWidth和videoHeight有效(非0)
|
||||
await _waitForValidVideoDimensions();
|
||||
// 如果视频参数未就绪,等待一段时间直到参数就绪或超时
|
||||
if (width == 0 || height == 0) {
|
||||
int attempts = 0;
|
||||
const maxAttempts = 20; // 最多等待2秒 (20 * 100ms)
|
||||
|
||||
while ((width == 0 || height == 0) && attempts < maxAttempts) {
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
width = StartChartManage().videoWidth;
|
||||
height = StartChartManage().videoHeight;
|
||||
attempts++;
|
||||
}
|
||||
|
||||
// 如果仍然没有获取到参数,使用默认值
|
||||
if (width == 0 || height == 0) {
|
||||
width = 864;
|
||||
height = 480;
|
||||
AppLog.log('使用默认视频参数: ${width}x$height');
|
||||
} else {
|
||||
AppLog.log('获取到视频参数: ${width}x$height');
|
||||
}
|
||||
}
|
||||
|
||||
// 创建解码器配置
|
||||
final config = VideoDecoderConfig(
|
||||
width: StartChartManage().videoWidth,
|
||||
width: width,
|
||||
// 实际视频宽度
|
||||
height: StartChartManage().videoHeight,
|
||||
height: height,
|
||||
codecType: 'h264',
|
||||
);
|
||||
AppLog.log('解码器配置的宽高为:${config.width}x${config.height}');
|
||||
// 初始化解码器并获取textureId
|
||||
final textureId = await VideoDecodePlugin.initDecoder(config);
|
||||
if (textureId != null) {
|
||||
@ -132,86 +154,6 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
||||
_initVideoDecoder(); // 重试初始化
|
||||
}
|
||||
}
|
||||
|
||||
// 等待有效的视频尺寸
|
||||
Future<void> _waitForValidVideoDimensions() async {
|
||||
int attempts = 0;
|
||||
const maxAttempts = 20; // 最多等待10秒 (20次 * 500ms)
|
||||
|
||||
while (attempts < maxAttempts) {
|
||||
// 检查videoWidth和videoHeight是否有效(非0)
|
||||
if (StartChartManage().videoWidth != 0 && StartChartManage().videoHeight != 0) {
|
||||
AppLog.log('获取到有效的视频尺寸: ${StartChartManage().videoWidth}x${StartChartManage().videoHeight}');
|
||||
return;
|
||||
}
|
||||
|
||||
attempts++;
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
AppLog.log('等待有效的视频尺寸... 第 $attempts 次, 当前尺寸: ${StartChartManage().videoWidth}x${StartChartManage().videoHeight}');
|
||||
}
|
||||
|
||||
// 如果等待超时,使用默认尺寸
|
||||
AppLog.log('等待视频尺寸超时,使用默认尺寸: 864x480');
|
||||
StartChartManage().videoWidth = 864;
|
||||
StartChartManage().videoHeight = 480;
|
||||
}
|
||||
|
||||
// iOS平台专用的视频解码器初始化方法,带有多次尝试逻辑
|
||||
Future<int?> _attemptVideoDecoderInitialization(VideoDecoderConfig config, {int maxAttempts = 3}) async {
|
||||
for (int attempt = 1; attempt <= maxAttempts; attempt++) {
|
||||
try {
|
||||
AppLog.log('视频解码器初始化第 $attempt 次尝试, 尺寸: ${config.width}x${config.height}');
|
||||
final textureId = await VideoDecodePlugin.initDecoder(config);
|
||||
if (textureId != null) {
|
||||
AppLog.log('视频解码器初始化第 $attempt 次尝试成功');
|
||||
return textureId;
|
||||
}
|
||||
|
||||
// 如果失败,等待一段时间再重试
|
||||
if (attempt < maxAttempts) {
|
||||
await Future.delayed(Duration(milliseconds: 500 * attempt));
|
||||
}
|
||||
} catch (e) {
|
||||
AppLog.log('视频解码器初始化第 $attempt 次尝试出错: $e');
|
||||
if (attempt < maxAttempts) {
|
||||
await Future.delayed(Duration(milliseconds: 500 * attempt));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果使用实际尺寸初始化失败,尝试使用默认尺寸
|
||||
AppLog.log('使用实际尺寸初始化失败,尝试使用默认尺寸重新初始化');
|
||||
final defaultConfig = VideoDecoderConfig(
|
||||
width: 864,
|
||||
height: 480,
|
||||
codecType: 'h264',
|
||||
);
|
||||
|
||||
for (int attempt = 1; attempt <= maxAttempts; attempt++) {
|
||||
try {
|
||||
AppLog.log('使用默认尺寸进行视频解码器初始化第 $attempt 次尝试');
|
||||
final textureId = await VideoDecodePlugin.initDecoder(defaultConfig);
|
||||
if (textureId != null) {
|
||||
AppLog.log('使用默认尺寸视频解码器初始化第 $attempt 次尝试成功');
|
||||
// 更新StartChartManage中的尺寸值
|
||||
StartChartManage().videoWidth = 864;
|
||||
StartChartManage().videoHeight = 480;
|
||||
return textureId;
|
||||
}
|
||||
|
||||
if (attempt < maxAttempts) {
|
||||
await Future.delayed(Duration(milliseconds: 500 * attempt));
|
||||
}
|
||||
} catch (e) {
|
||||
AppLog.log('使用默认尺寸视频解码器初始化第 $attempt 次尝试出错: $e');
|
||||
if (attempt < maxAttempts) {
|
||||
await Future.delayed(Duration(milliseconds: 500 * attempt));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// 初始化音频播放器
|
||||
void _initFlutterPcmSound() {
|
||||
@ -340,7 +282,6 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
||||
AppLog.log('启动帧处理定时器,目标帧率: ${state.targetFps}fps,间隔: ${intervalMs}ms');
|
||||
}
|
||||
|
||||
/// 从缓冲区处理下一帧
|
||||
/// 从缓冲区处理下一帧
|
||||
void _processNextFrameFromBuffer() async {
|
||||
final startTime = DateTime.now().microsecondsSinceEpoch;
|
||||
@ -377,7 +318,6 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
||||
final int? frameSeq = frameMap['frameSeq'];
|
||||
final int? frameSeqI = frameMap['frameSeqI'];
|
||||
final int? pts = frameMap['pts'];
|
||||
final ScpMessage? scpMessage = frameMap['scpMessage'];
|
||||
if (frameData == null || frameType == null || frameSeq == null || frameSeqI == null || pts == null) {
|
||||
state.isProcessingFrame = false;
|
||||
return;
|
||||
@ -422,7 +362,6 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
||||
final int? frameSeq = frameMap['frameSeq'];
|
||||
final int? frameSeqI = frameMap['frameSeqI'];
|
||||
final int? pts = frameMap['pts'];
|
||||
final ScpMessage? scpMessage = frameMap['scpMessage'];
|
||||
if (frameData == null || frameType == null || frameSeq == null || frameSeqI == null || pts == null) {
|
||||
state.isProcessingFrame = false;
|
||||
return;
|
||||
@ -631,8 +570,6 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
||||
// 在没有监听成功之前赋值一遍状态
|
||||
// *** 由于页面会在状态变化之后才会初始化,导致识别不到最新的状态,在这里手动赋值 ***
|
||||
state.talkStatus.value = state.startChartTalkStatus.status;
|
||||
AppLog.log("初始化对讲状态111111:${state.startChartTalkStatus.status}");
|
||||
AppLog.log("初始化对讲状态222222:${state.talkStatus.value}");
|
||||
|
||||
// 初始化音频播放器
|
||||
_initFlutterPcmSound();
|
||||
@ -642,9 +579,6 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
||||
|
||||
requestPermissions();
|
||||
|
||||
// 启动视频尺寸监听器
|
||||
_startVideoDimensionListener();
|
||||
|
||||
// 初始化视频解码器
|
||||
_initVideoDecoder();
|
||||
|
||||
@ -685,7 +619,6 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
||||
|
||||
// 取消数据流监听
|
||||
_streamSubscription?.cancel();
|
||||
_streamSubscription = null;
|
||||
_isListening = false;
|
||||
|
||||
// 重置期望数据
|
||||
@ -702,11 +635,6 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
||||
_startProcessingAudioTimer?.cancel();
|
||||
_startProcessingAudioTimer = null;
|
||||
_bufferedAudioFrames.clear();
|
||||
|
||||
// 取消视频尺寸监听器
|
||||
_videoDimensionCheckTimer?.cancel();
|
||||
_videoDimensionCheckTimer = null;
|
||||
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
@ -1017,21 +945,6 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
||||
}
|
||||
}
|
||||
|
||||
// 监听视频尺寸变化,当它们更新时尝试初始化解码器(如果尚未初始化)
|
||||
void _startVideoDimensionListener() {
|
||||
_videoDimensionCheckTimer = Timer.periodic(const Duration(milliseconds: 500), (timer) {
|
||||
// 检查是否已经有有效的videoWidth和videoHeight,且解码器尚未初始化
|
||||
if (state.textureId.value == null &&
|
||||
StartChartManage().videoWidth != 0 &&
|
||||
StartChartManage().videoHeight != 0 ) {
|
||||
// 尝试初始化解码器(如果尚未初始化)
|
||||
if (state.textureId.value == null) {
|
||||
_initVideoDecoder();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _processFrame(TalkDataModel talkDataModel) {
|
||||
final talkData = talkDataModel.talkData;
|
||||
final talkDataH264Frame = talkDataModel.talkDataH264Frame;
|
||||
@ -1071,4 +984,4 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -86,7 +86,9 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage> wit
|
||||
quarterTurns: startChartManage.rotateAngle ~/ 90,
|
||||
child: state.isFullScreen.isFalse
|
||||
? AspectRatio(
|
||||
aspectRatio: StartChartManage().videoWidth / StartChartManage().videoHeight,
|
||||
aspectRatio: StartChartManage().videoWidth > 0 && StartChartManage().videoHeight > 0
|
||||
? StartChartManage().videoWidth / StartChartManage().videoHeight
|
||||
: 864 / 480,
|
||||
child: Texture(
|
||||
textureId: state.textureId.value!,
|
||||
filterQuality: FilterQuality.medium,
|
||||
|
||||
@ -135,8 +135,13 @@ class _TalkViewPageState extends State<TalkViewPage>
|
||||
if (state.listData.value.isEmpty) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
final int videoW = startChartManage.videoWidth;
|
||||
final int videoH = startChartManage.videoHeight;
|
||||
int videoW = startChartManage.videoWidth;
|
||||
int videoH = startChartManage.videoHeight;
|
||||
// 如果视频参数未就绪,使用默认值
|
||||
if (videoW == 0 || videoH == 0) {
|
||||
videoW = 864;
|
||||
videoH = 480;
|
||||
}
|
||||
if (videoW == 320 && videoH == 240) {
|
||||
return Positioned(
|
||||
top: 150.h,
|
||||
@ -640,6 +645,11 @@ class _TalkViewPageState extends State<TalkViewPage>
|
||||
double barWidth = 1.sw - 30.w * 2;
|
||||
int videoW = startChartManage.videoWidth;
|
||||
int videoH = startChartManage.videoHeight;
|
||||
// 如果视频参数未就绪,使用默认值
|
||||
if (videoW == 0 || videoH == 0) {
|
||||
videoW = 864;
|
||||
videoH = 480;
|
||||
}
|
||||
int quarterTurns = startChartManage.rotateAngle ~/ 90;
|
||||
bool isRotated = quarterTurns % 2 == 1;
|
||||
// 旋转后宽高互换
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user