WIP MJPEG stream handling

This commit is contained in:
Yegor Vialov 2019-01-31 01:04:13 +02:00
parent 5897fa3a99
commit 29a94c882f
3 changed files with 88 additions and 4 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${this.entityPicture}', url: 'https://citadel.vynn.co:8123/api/camera_proxy_stream/camera.demo_camera?token=${this.attributes['access_token']}',
); );
} }
} }

View File

@ -16,15 +16,97 @@ class _CameraControlsWidgetState extends State<CameraControlsWidget> {
void initState() { void initState() {
super.initState(); super.initState();
Logger.d("Camera source: ${widget.url}"); Logger.d("Camera source: ${widget.url}");
_getData();
}
http.Client client;
http.StreamedResponse response;
List<int> binaryImage = [];
void _getData() async {
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
//Log.d
Logger.d("==Sending");
response = await client.send(request); // sends request and waits for response stream
Logger.d("==Reading");
int byteCount = 0;
Logger.d("==${response.headers}");
List<int> primaryBuffer=[];
List<int> secondaryBuffer=[];
int imageStart = 0;
int imageEnd = 0;
response.stream.transform(
StreamTransformer.fromHandlers(
handleData: (data, sink) {
primaryBuffer.addAll(data);
Logger.d("== data recived: ${data.length}");
Logger.d("== primary buffer size: ${primaryBuffer.length}");
//Logger.d("${data.toString()}");
for (int i = 0; i < primaryBuffer.length - 15; i++) {
String startBoundary = utf8.decode(primaryBuffer.sublist(i, i+15),allowMalformed: true);
if (startBoundary == "--frameboundary") {
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;
}*/
}
for (int i = imageStart+15; i < primaryBuffer.length - 15; i++) {
String endBoundary = utf8.decode(primaryBuffer.sublist(i, i+15),allowMalformed: true);
if (endBoundary == "--frameboundary") {
Logger.d("==END found");
imageEnd = i;
sink.add(primaryBuffer.sublist(imageStart, imageEnd - 1));
primaryBuffer = primaryBuffer.sublist(imageEnd);
break;
}
}
//byteCount += data.length;
//Logger.d("$byteCount");
},
handleError: (error, stack, sink) {},
handleDone: (sink) {
sink.close();
},
)
).listen((d) {
setState(() {
binaryImage = d;
});
//Logger.d("==binary imagesize=${d.length}");
});
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Column( return Column(
children: <Widget>[ children: <Widget>[
Image.network( Image.memory(Uint8List.fromList(binaryImage)),
"${widget.url}",
),
FlatButton( FlatButton(
child: Text("VIEW"), child: Text("VIEW"),
onPressed: () { onPressed: () {
@ -46,6 +128,7 @@ class _CameraControlsWidgetState extends State<CameraControlsWidget> {
@override @override
void dispose() { void dispose() {
client.close();
super.dispose(); super.dispose();
} }
} }

View File

@ -1,5 +1,6 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:async'; import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';