fix:完成720P 20帧渲染需求
This commit is contained in:
parent
419912c590
commit
e806987fa0
@ -19,12 +19,14 @@ class VideoTypeE extends $pb.ProtobufEnum {
|
|||||||
static const VideoTypeE H264 = VideoTypeE._(1, _omitEnumNames ? '' : 'H264');
|
static const VideoTypeE H264 = VideoTypeE._(1, _omitEnumNames ? '' : 'H264');
|
||||||
static const VideoTypeE IMAGE = VideoTypeE._(2, _omitEnumNames ? '' : 'IMAGE');
|
static const VideoTypeE IMAGE = VideoTypeE._(2, _omitEnumNames ? '' : 'IMAGE');
|
||||||
static const VideoTypeE VP8 = VideoTypeE._(3, _omitEnumNames ? '' : 'VP8');
|
static const VideoTypeE VP8 = VideoTypeE._(3, _omitEnumNames ? '' : 'VP8');
|
||||||
|
static const VideoTypeE H264_720P = VideoTypeE._(4, _omitEnumNames ? '' : 'H264_720P');
|
||||||
|
|
||||||
static const $core.List<VideoTypeE> values = <VideoTypeE> [
|
static const $core.List<VideoTypeE> values = <VideoTypeE> [
|
||||||
NONE_V,
|
NONE_V,
|
||||||
H264,
|
H264,
|
||||||
IMAGE,
|
IMAGE,
|
||||||
VP8,
|
VP8,
|
||||||
|
H264_720P,
|
||||||
];
|
];
|
||||||
|
|
||||||
static final $core.Map<$core.int, VideoTypeE> _byValue = $pb.ProtobufEnum.initByValue(values);
|
static final $core.Map<$core.int, VideoTypeE> _byValue = $pb.ProtobufEnum.initByValue(values);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -56,6 +56,7 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage>
|
|||||||
state.animationController.forward();
|
state.animationController.forward();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -71,6 +72,7 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage>
|
|||||||
child: Stack(
|
child: Stack(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
// 悬浮帧率统计信息条
|
||||||
Obx(
|
Obx(
|
||||||
() {
|
() {
|
||||||
final double screenWidth = MediaQuery.of(context).size.width;
|
final double screenWidth = MediaQuery.of(context).size.width;
|
||||||
@ -93,32 +95,84 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage>
|
|||||||
final double scaleWidth = physicalWidth / rotatedImageWidth;
|
final double scaleWidth = physicalWidth / rotatedImageWidth;
|
||||||
final double scaleHeight = physicalHeight / rotatedImageHeight;
|
final double scaleHeight = physicalHeight / rotatedImageHeight;
|
||||||
max(scaleWidth, scaleHeight); // 选择较大的缩放比例
|
max(scaleWidth, scaleHeight); // 选择较大的缩放比例
|
||||||
|
return Column(
|
||||||
return state.isLoading.isTrue
|
children: [
|
||||||
? Image.asset(
|
Expanded(
|
||||||
'images/main/monitorBg.png',
|
child: state.isLoading.isTrue
|
||||||
width: screenWidth,
|
? Image.asset(
|
||||||
height: screenHeight,
|
'images/main/monitorBg.png',
|
||||||
fit: BoxFit.cover,
|
width: screenWidth,
|
||||||
)
|
height: screenHeight,
|
||||||
: PopScope(
|
fit: BoxFit.cover,
|
||||||
canPop: false,
|
)
|
||||||
child: RepaintBoundary(
|
: PopScope(
|
||||||
key: state.globalKey,
|
canPop: false,
|
||||||
child: SizedBox.expand(
|
child: RepaintBoundary(
|
||||||
child: RotatedBox(
|
key: state.globalKey,
|
||||||
// 解码器不支持硬件旋转,使用RotatedBox
|
child: SizedBox.expand(
|
||||||
quarterTurns: -1,
|
child: RotatedBox(
|
||||||
child: Texture(
|
// 解码器不支持硬件旋转,使用RotatedBox
|
||||||
textureId: state.textureId.value!,
|
quarterTurns: -1,
|
||||||
filterQuality: FilterQuality.medium,
|
child: Texture(
|
||||||
|
textureId: state.textureId.value!,
|
||||||
|
filterQuality: FilterQuality.medium,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
Positioned(
|
||||||
|
top: 300.h,
|
||||||
|
right: 20.w,
|
||||||
|
child: Obx(() => Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.black.withOpacity(0.5),
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.network_check, color: Colors.redAccent, size: 18),
|
||||||
|
SizedBox(width: 6),
|
||||||
|
Text(
|
||||||
|
'接受服务端H264帧率/秒: ',
|
||||||
|
style: TextStyle(color: Colors.white, fontSize: 15),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'${state.networkH264Fps.value}',
|
||||||
|
style: TextStyle(color: Colors.redAccent, fontSize: 16, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
Text(' fps', style: TextStyle(color: Colors.white, fontSize: 13)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 4),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.send, color: Colors.blueAccent, size: 18),
|
||||||
|
SizedBox(width: 6),
|
||||||
|
Text(
|
||||||
|
'送入Native帧率/秒: ',
|
||||||
|
style: TextStyle(color: Colors.white, fontSize: 15),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'${state.nativeSendFps.value}',
|
||||||
|
style: TextStyle(color: Colors.blueAccent, fontSize: 16, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
Text(' fps', style: TextStyle(color: Colors.white, fontSize: 13)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
),
|
||||||
Obx(() => state.isLoading.isTrue
|
Obx(() => state.isLoading.isTrue
|
||||||
? Positioned(
|
? Positioned(
|
||||||
bottom: 310.h,
|
bottom: 310.h,
|
||||||
@ -127,102 +181,6 @@ class _TalkViewNativeDecodePageState extends State<TalkViewNativeDecodePage>
|
|||||||
style: TextStyle(color: Colors.black, fontSize: 26.sp),
|
style: TextStyle(color: Colors.black, fontSize: 26.sp),
|
||||||
))
|
))
|
||||||
: Container()),
|
: Container()),
|
||||||
Obx(() => state.textureId.value != null && state.showFps.value
|
|
||||||
? Positioned(
|
|
||||||
top: ScreenUtil().statusBarHeight + 10.h,
|
|
||||||
right: 20.w,
|
|
||||||
child: Container(
|
|
||||||
padding:
|
|
||||||
EdgeInsets.symmetric(horizontal: 10.w, vertical: 5.h),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.black.withOpacity(0.5),
|
|
||||||
borderRadius: BorderRadius.circular(5.h),
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
|
||||||
children: <Widget>[
|
|
||||||
// Text(
|
|
||||||
// 'FPS: ${state.decoderFps.value.toStringAsFixed(1)}',
|
|
||||||
// style: TextStyle(
|
|
||||||
// color: _getPacketLossColor(
|
|
||||||
// state.packetLossRate.value),
|
|
||||||
// fontSize: 20.sp,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
Text(
|
|
||||||
'丢包率: ${state.packetLossRate.value.toStringAsFixed(1)}%',
|
|
||||||
style: TextStyle(
|
|
||||||
color: _getPacketLossColor(
|
|
||||||
state.packetLossRate.value),
|
|
||||||
fontSize: 20.sp,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
'消息丢失: ${state.messageLossRate.value.toStringAsFixed(1)}%',
|
|
||||||
style: TextStyle(
|
|
||||||
color: _getPacketLossColor(
|
|
||||||
state.messageLossRate.value),
|
|
||||||
fontSize: 20.sp,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Divider(
|
|
||||||
color: Colors.white30,
|
|
||||||
height: 10.h,
|
|
||||||
thickness: 1),
|
|
||||||
Text(
|
|
||||||
'已渲染帧: ${state.renderedFrameCount.value}',
|
|
||||||
style:
|
|
||||||
TextStyle(color: Colors.white, fontSize: 18.sp),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
'总帧数: ${state.totalFrames.value}',
|
|
||||||
style:
|
|
||||||
TextStyle(color: Colors.white, fontSize: 18.sp),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
'丢弃帧: ${state.droppedFrames.value}',
|
|
||||||
style:
|
|
||||||
TextStyle(color: Colors.white, fontSize: 18.sp),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
'IDR帧: ${state.hasSentIDR.value ? "已发送" : "未发送"}',
|
|
||||||
style: TextStyle(
|
|
||||||
color: state.hasSentIDR.value
|
|
||||||
? Colors.green
|
|
||||||
: Colors.red,
|
|
||||||
fontSize: 18.sp),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
'SPS: ${state.hasSentSPS.value ? "已发送" : "未发送"}',
|
|
||||||
style: TextStyle(
|
|
||||||
color: state.hasSentSPS.value
|
|
||||||
? Colors.green
|
|
||||||
: Colors.red,
|
|
||||||
fontSize: 18.sp),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
'PPS: ${state.hasSentPPS.value ? "已发送" : "未发送"}',
|
|
||||||
style: TextStyle(
|
|
||||||
color: state.hasSentPPS.value
|
|
||||||
? Colors.green
|
|
||||||
: Colors.red,
|
|
||||||
fontSize: 18.sp),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
'keyFrameInterval: ${state.keyFrameInterval.value}',
|
|
||||||
style:
|
|
||||||
TextStyle(color: Colors.green, fontSize: 18.sp),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
'decodingJitterMs: ${state.decodingJitterMs.value}',
|
|
||||||
style:
|
|
||||||
TextStyle(color: Colors.green, fontSize: 18.sp),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Container()),
|
|
||||||
Obx(() => state.isLoading.isFalse && state.oneMinuteTime.value > 0
|
Obx(() => state.isLoading.isFalse && state.oneMinuteTime.value > 0
|
||||||
? Positioned(
|
? Positioned(
|
||||||
top: ScreenUtil().statusBarHeight + 75.h,
|
top: ScreenUtil().statusBarHeight + 75.h,
|
||||||
|
|||||||
@ -106,4 +106,19 @@ class TalkViewNativeDecodeState {
|
|||||||
|
|
||||||
// 帧跟踪Map,记录每个提交的帧,key为textureId_frameSeq
|
// 帧跟踪Map,记录每个提交的帧,key为textureId_frameSeq
|
||||||
Map<String, Map<String, dynamic>> frameTracker = {};
|
Map<String, Map<String, dynamic>> frameTracker = {};
|
||||||
|
|
||||||
|
// H264帧缓冲区相关
|
||||||
|
final List<Map<String, dynamic>> h264FrameBuffer = <Map<String, dynamic>>[]; // H264帧缓冲区,存储帧数据和类型
|
||||||
|
final int maxFrameBufferSize = 25; // 最大缓冲区大小
|
||||||
|
final int targetFps = 120; // 目标解码帧率
|
||||||
|
Timer? frameProcessTimer; // 帧处理定时器
|
||||||
|
bool isProcessingFrame = false; // 是否正在处理帧
|
||||||
|
int lastProcessedTimestamp = 0; // 上次处理帧的时间戳
|
||||||
|
// H264文件保存相关
|
||||||
|
String? h264FilePath;
|
||||||
|
File? h264File;
|
||||||
|
|
||||||
|
// 新增:用于页面显示的帧率统计
|
||||||
|
RxInt networkH264Fps = 0.obs;
|
||||||
|
RxInt nativeSendFps = 0.obs;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user