WIP #143 Initial not optimized MJPEG streaming

This commit is contained in:
Yegor Vialov
2019-02-08 23:59:33 +02:00
parent 71c0e2caa0
commit 8814687be6
4 changed files with 43 additions and 79 deletions

View File

@ -13,7 +13,7 @@ class CameraEntity extends Entity {
@override @override
Widget _buildAdditionalControlsForPage(BuildContext context) { Widget _buildAdditionalControlsForPage(BuildContext context) {
return CameraControlsWidget( return CameraControlsWidget(
url: 'https://citadel.vynn.co:8123/api/camera_proxy_stream/camera.demo_camera?token=${this.attributes['access_token']}', url: '$homeAssistantWebHost/api/camera_proxy_stream/camera.demo_camera?token=${this.attributes['access_token']}',
); );
} }
} }

View File

@ -86,9 +86,9 @@ class EntityCollection {
case "fan": { case "fan": {
return FanEntity(rawEntityData); return FanEntity(rawEntityData);
} }
/*case "camera": { case "camera": {
return CameraEntity(rawEntityData); return CameraEntity(rawEntityData);
}*/ }
case "alarm_control_panel": { case "alarm_control_panel": {
return AlarmControlPanelEntity(rawEntityData); return AlarmControlPanelEntity(rawEntityData);
} }

View File

@ -15,8 +15,6 @@ class _CameraControlsWidgetState extends State<CameraControlsWidget> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
Logger.d("Camera source: ${widget.url}");
_getData(); _getData();
} }
@ -26,68 +24,46 @@ class _CameraControlsWidgetState extends State<CameraControlsWidget> {
void _getData() async { void _getData() async {
client = new http.Client(); // create a client to make api calls client = new http.Client(); // create a client to make api calls
http.Request request = new http.Request("GET", Uri.parse(widget.url)); // create get request http.Request request = new http.Request("GET", Uri.parse(widget.url)); // create get request
//Log.d Logger.d("[Sending] ==> ${widget.url}");
Logger.d("==Sending");
response = await client.send(request); // sends request and waits for response stream response = await client.send(request); // sends request and waits for response stream
Logger.d("==Reading"); Logger.d("[Received] <== ${response.headers}");
int byteCount = 0;
Logger.d("==${response.headers}");
List<int> primaryBuffer=[]; List<int> primaryBuffer=[];
List<int> secondaryBuffer=[]; int imageSizeStart = 0;
int imageSizeEnd = 0;
int imageStart = 0; int imageStart = 0;
int imageEnd = 0;
response.stream.transform( response.stream.transform(
StreamTransformer.fromHandlers( StreamTransformer.fromHandlers(
handleData: (data, sink) { handleData: (data, sink) {
primaryBuffer.addAll(data); primaryBuffer.addAll(data);
Logger.d("== data recived: ${data.length}"); if (primaryBuffer.length >= 40) {
Logger.d("== primary buffer size: ${primaryBuffer.length}"); for (int i = 15; i < primaryBuffer.length - 16; i++) {
//Logger.d("${data.toString()}"); String tmp1 = utf8.decode(
for (int i = 0; i < primaryBuffer.length - 15; i++) { primaryBuffer.sublist(i, i + 16), allowMalformed: true);
String startBoundary = utf8.decode(primaryBuffer.sublist(i, i+15),allowMalformed: true); if (tmp1 == "Content-Length: ") {
if (startBoundary == "--frameboundary") { imageSizeStart = i + 16;
Logger.d("== START found at $i");
imageStart = i;
//secondaryBuffer.addAll(primaryBuffer.sublist(i));
//Logger.d("== secondary.length=${secondaryBuffer.length}. clearinig primary");
//primaryBuffer.clear();
break;
}
/*String startBoundary = utf8.decode(primaryBuffer.sublist(i, i+4),allowMalformed: true);
if (startBoundary == "\r\n\r\n") {
Logger.d("==Binary image start found ($i). primary.length=${primaryBuffer.length}");
secondaryBuffer.addAll(primaryBuffer.sublist(i+5));
Logger.d("==secondary.length=${secondaryBuffer.length}. clearinig primary");
primaryBuffer.clear();
Logger.d("==secondary.length=${secondaryBuffer.length}");
for (int j = 0; j < secondaryBuffer.length - 15; j++) {
String endBoundary = utf8.decode(secondaryBuffer.sublist(j, j+15),allowMalformed: true);
if (endBoundary == "--frameboundary") {
Logger.d("==Binary image end found");
sink.add(secondaryBuffer.sublist(0, j-1));
primaryBuffer.addAll(secondaryBuffer.sublist(j));
secondaryBuffer.clear();
break; break;
} }
} }
break; for (int i = imageSizeStart; i < primaryBuffer.length - 4; i++) {
}*/ String tmp1 = utf8.decode(
} primaryBuffer.sublist(i, i + 4), allowMalformed: true);
for (int i = imageStart+15; i < primaryBuffer.length - 15; i++) { if (tmp1 == "\r\n\r\n") {
String endBoundary = utf8.decode(primaryBuffer.sublist(i, i+15),allowMalformed: true); imageSizeEnd = i;
if (endBoundary == "--frameboundary") { imageStart = i + 4;
Logger.d("==END found");
imageEnd = i;
sink.add(primaryBuffer.sublist(imageStart, imageEnd - 1));
primaryBuffer = primaryBuffer.sublist(imageEnd);
break; break;
} }
} }
//byteCount += data.length; int imageSize = int.tryParse(utf8.decode(
//Logger.d("$byteCount"); primaryBuffer.sublist(imageSizeStart, imageSizeEnd),
allowMalformed: true));
//Logger.d("== imageSize=$imageSize");
if (primaryBuffer.length >= imageStart + imageSize) {
sink.add(
primaryBuffer.sublist(imageStart, imageStart + imageSize));
primaryBuffer = primaryBuffer.sublist(imageStart + imageSize);
}
}
}, },
handleError: (error, stack, sink) {}, handleError: (error, stack, sink) {},
handleDone: (sink) { handleDone: (sink) {
@ -98,32 +74,20 @@ class _CameraControlsWidgetState extends State<CameraControlsWidget> {
setState(() { setState(() {
binaryImage = d; binaryImage = d;
}); });
//Logger.d("==binary imagesize=${d.length}");
}); });
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (binaryImage.isEmpty) {
return Text("Loading...");
} else {
return Column( return Column(
children: <Widget>[ children: <Widget>[
Image.memory(Uint8List.fromList(binaryImage)), Image.memory(Uint8List.fromList(binaryImage), gaplessPlayback: true),
FlatButton(
child: Text("VIEW"),
onPressed: () {
setState(() {
});
},
)
], ],
); );
return Image.network("${widget.url}"); }
return FlatButton(
child: Text("VIEW"),
onPressed: () {
HAUtils.launchURL(widget.url);
},
);
} }
@override @override

View File

@ -367,10 +367,10 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
GestureDetector( GestureDetector(
onTap: () { onTap: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
HAUtils.launchURL("http://www.vynn.co/"); HAUtils.launchURL("http://ha-client.vynn.co/");
}, },
child: Text( child: Text(
"www.vynn.co", "ha-client.vynn.co",
style: TextStyle( style: TextStyle(
color: Colors.blue, color: Colors.blue,
decoration: TextDecoration.underline decoration: TextDecoration.underline