fix:增加读取h264文件后使用定时器发送,调整html样式

This commit is contained in:
liyi 2024-12-12 15:48:15 +08:00
parent 5b2cd50879
commit f3e42e3ac8
3 changed files with 119 additions and 27 deletions

View File

@ -6,8 +6,19 @@
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>play</title> <title>play</title>
</head> </head>
<style>
html{
margin:0 0;
padding: 0 0;
}
body{
margin:0 0;
padding: 0 0;
}
</style>
<body> <body>
<video controls autoplay muted style="width: 100vw;height: 100vh;" id="player"> <video autoplay muted style="width: 100vw;height: 100vh;" poster="images/loader-thumb.jpg" id="player">
</video> </video>
<script> <script>
(function (global, factory) { (function (global, factory) {
@ -2644,7 +2655,7 @@
jmuxer = new JMuxer({ jmuxer = new JMuxer({
node: 'player', node: 'player',
mode: 'video', mode: 'video',
flushingTime: 0, flushingTime: 1000,
fps: 22, fps: 22,
debug: true, debug: true,
}); });

View File

@ -1,6 +1,9 @@
import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show ByteData, Uint8List, rootBundle; import 'package:flutter/services.dart' show ByteData, Uint8List, rootBundle;
import 'package:star_lock/app_settings/app_colors.dart';
import 'package:star_lock/tools/titleAppBar.dart';
import 'package:webview_flutter/webview_flutter.dart'; import 'package:webview_flutter/webview_flutter.dart';
class LocalHtmlPage extends StatefulWidget { class LocalHtmlPage extends StatefulWidget {
@ -34,32 +37,52 @@ class _LocalHtmlPageState extends State<LocalHtmlPage> {
final ByteData data = await rootBundle.load('assets/talk.h264'); final ByteData data = await rootBundle.load('assets/talk.h264');
final List<int> byteData = data.buffer.asUint8List(); final List<int> byteData = data.buffer.asUint8List();
int offset = 0; // NALU chunks
int frameSize = 0; final List<int> chunks = extractChunks(byteData);
final int total = chunks.length;
// H.264 int current = 0;
while (offset < byteData.length) { int start = 0;
// int end = 0;
frameSize = getFrameSize(byteData, offset); List<int> buffer = []; //
Timer? timer;
if (frameSize == 0) { // 800
print("No more frames or error in frame size calculation."); timer ??= Timer.periodic(Duration(milliseconds: 800), (timer) async {
break; // 退 if (current >= total) {
current = 0;
start = 0;
print("All frames sent. Restarting from the beginning.");
} }
// end = chunks[current];
List<int> frameData = byteData.sublist(offset, offset + frameSize); current++;
// WebView feedDataFromFlutter //
String jsCode = "feedDataFromFlutter(${frameData});"; List<int> frameData = byteData.sublist(start, end);
await _controller.runJavaScript(jsCode); buffer.addAll(frameData);
start = end;
// //
offset += frameSize; if (buffer.isNotEmpty) {
await _sendBufferedData(buffer);
buffer.clear(); //
}
// 22 //
await Future.delayed(Duration(milliseconds: (1000 / 22).toInt())); if (current % 50 == 0) {
} print("I am serving, no problem!");
}
if (current == 0) {
print("Started from first chunk...");
}
//
if (current >= total) {
timer.cancel();
print('All frames sent. Stopping timer...');
}
});
} }
int getFrameSize(List<int> data, int offset) { int getFrameSize(List<int> data, int offset) {
@ -128,10 +151,69 @@ class _LocalHtmlPageState extends State<LocalHtmlPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar(
title: Text("加载本地 HTML"),
),
body: WebViewWidget(controller: _controller), body: WebViewWidget(controller: _controller),
); );
} }
_sendBufferedData(List<int> buffer) async {
String jsCode = "feedDataFromFlutter(${buffer});";
await _controller.runJavaScript(jsCode);
}
// NALU chunks
List<int> extractChunks(List<int> byteData) {
int i = 0;
int length = byteData.length;
int naluCount = 0;
int value;
int state = 0;
int lastIndex = 0;
List<int> result = [];
const minNaluPerChunk = 30; // NALU数量
while (i < length) {
value = byteData[i++];
// finding 3 or 4-byte start codes (00 00 01 OR 00 00 00 01)
switch (state) {
case 0:
if (value == 0) {
state = 1;
}
break;
case 1:
if (value == 0) {
state = 2;
} else {
state = 0;
}
break;
case 2:
case 3:
if (value == 0) {
state = 3;
} else if (value == 1 && i < length) {
if (lastIndex > 0) {
naluCount++;
}
if (naluCount >= minNaluPerChunk) {
result.add(lastIndex - state - 1);
naluCount = 0;
}
state = 0;
lastIndex = i;
} else {
state = 0;
}
break;
default:
break;
}
}
if (naluCount > 0) {
result.add(lastIndex);
}
return result;
}
} }

View File

@ -22,18 +22,17 @@ class UdpTalkAcceptHandler extends ScpMessageBaseHandle
} }
@override @override
void handleResp(ScpMessage scpMessage) async { void handleResp(ScpMessage scpMessage) {
// //
final GenericResp genericResp = scpMessage.Payload; final GenericResp genericResp = scpMessage.Payload;
if (checkGenericRespSuccess(genericResp)) { if (checkGenericRespSuccess(genericResp)) {
// //
_handleStartTalkPing(); _handleStartTalkPing();
await Future.delayed(Duration(seconds: 2), () { Future.delayed(Duration(seconds: 2), () {
// //
_handleStartSendTalkExpectDataRequest(); _handleStartSendTalkExpectDataRequest();
// //
_handleCheckTalkDataTimer(); _handleCheckTalkDataTimer();
}); });
// //
stopRingtone(); stopRingtone();