WIP #143 Initial not optimized MJPEG streaming
This commit is contained in:
@ -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']}',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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");
|
break;
|
||||||
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 = imageSizeStart; i < primaryBuffer.length - 4; i++) {
|
||||||
}
|
String tmp1 = utf8.decode(
|
||||||
for (int i = imageStart+15; i < primaryBuffer.length - 15; i++) {
|
primaryBuffer.sublist(i, i + 4), allowMalformed: true);
|
||||||
String endBoundary = utf8.decode(primaryBuffer.sublist(i, i+15),allowMalformed: true);
|
if (tmp1 == "\r\n\r\n") {
|
||||||
if (endBoundary == "--frameboundary") {
|
imageSizeEnd = i;
|
||||||
Logger.d("==END found");
|
imageStart = i + 4;
|
||||||
imageEnd = i;
|
break;
|
||||||
sink.add(primaryBuffer.sublist(imageStart, imageEnd - 1));
|
}
|
||||||
primaryBuffer = primaryBuffer.sublist(imageEnd);
|
}
|
||||||
break;
|
int imageSize = int.tryParse(utf8.decode(
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//byteCount += data.length;
|
|
||||||
//Logger.d("$byteCount");
|
|
||||||
|
|
||||||
},
|
},
|
||||||
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) {
|
||||||
return Column(
|
if (binaryImage.isEmpty) {
|
||||||
children: <Widget>[
|
return Text("Loading...");
|
||||||
Image.memory(Uint8List.fromList(binaryImage)),
|
} else {
|
||||||
FlatButton(
|
return Column(
|
||||||
child: Text("VIEW"),
|
children: <Widget>[
|
||||||
onPressed: () {
|
Image.memory(Uint8List.fromList(binaryImage), gaplessPlayback: true),
|
||||||
setState(() {
|
],
|
||||||
|
);
|
||||||
});
|
}
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
return Image.network("${widget.url}");
|
|
||||||
return FlatButton(
|
|
||||||
child: Text("VIEW"),
|
|
||||||
onPressed: () {
|
|
||||||
HAUtils.launchURL(widget.url);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user