This commit is contained in:
lxsang 2020-12-30 01:29:23 +00:00
parent 562f863728
commit 979dd64738
9 changed files with 32 additions and 22 deletions

View File

@ -1,9 +1,11 @@
# RemoteCamera
Connect to a V4L2 camera on server via Antunnel.
Connect to a V4L2 camera on server via Antunnel plugin.
![](https://raw.githubusercontent.com/lxsang/antosdk-apps/master/RemoteCamera/screenshot.jpg)
This application reauires the **tunel plugin** and the **ant-tunnel v4l2 publisher**
on the server-side
## Change log
* v0.1.2-a: user worker for jpeg decoding
* v0.1.2-a: user worker for jpeg decoding

View File

@ -31,12 +31,14 @@ decode = (arr) =>
}
onmessage = (e) => {
if(e.data.libjpeg)
{
importScripts(e.data.libjpeg);
}
else
{
decode(e.data);
switch (e.data.cmd) {
case 0x0:
importScripts(e.data.data);
break;
case 0x1:
decode(e.data.data);
break;
default:
console.error("Unknown command " + e.data.cmd);
}
}

View File

@ -1 +1 @@
(function(){var t;(t=class extends this.OS.application.BaseApplication{constructor(t){super("RemoteCamera",t)}main(){var t,e,s;for(this.decoder=new Worker("pkg://RemoteCamera/decoder.js".asFileHandle().getlink()),this.decoder.onmessage=t=>this.paint(t.data),this.decoder.postMessage({libjpeg:"pkg://libjpeg/jpg.js".asFileHandle().getlink()}),this.mute=!1,this.player=this.find("player"),this.qctl=this.find("qctl"),this.fpsctl=this.find("fpsctl"),this.cam_setting={w:640,h:480,fps:10,quality:60},t=[],e=s=5;s<=30;e=s+=5)t.push({text:""+e,value:e});return this.fpsctl.data=t,this.fpsctl.selected=this.cam_setting.fps/5-1,this.fpsctl.onlistselect=t=>{if(!this.mute)return this.cam_setting.fps=t.data.item.data.value,this.setCameraSetting()},this.qctl.value=this.cam_setting.quality,this.resoctl=this.find("resoctl"),this.resoctl.data=[{text:__("320x240"),mode:"qvga"},{text:__("640x480"),selected:!0,mode:"vga"},{text:__("800x600"),mode:"svga"},{text:__("1024x760"),mode:"hd"},{text:__("1920×1080"),mode:"fhd"}],this.resoctl.onlistselect=t=>{if(!this.mute){switch(t.data.item.data.mode){case"qvga":this.cam_setting.w=320,this.cam_setting.h=240;break;case"vga":this.cam_setting.w=640,this.cam_setting.h=480;break;case"svga":this.cam_setting.w=800,this.cam_setting.h=600;break;case"hd":this.cam_setting.w=1024,this.cam_setting.h=768;break;case"fhd":this.cam_setting.w=1920,this.cam_setting.h=1080}return this.setCameraSetting()}},this.qctl.onvaluechange=t=>{if(!this.mute)return this.cam_setting.quality=t.data,this.setCameraSetting()},Antunnel.tunnel?this.setting.channel?this.openSession():this.requestChannel():this.notify(__("Antunnel service is not available"))}requestChannel(){return this.openDialog("PromptDialog",{title:__("Enter camera channel"),label:__("Please enter camera channel name")}).then(t=>(this.setting.channel=t,this.sub?(this.sub.onclose=t=>this.openSession(),this.sub.close()):this.openSession()))}paint(t){var e,s,i;return s=new Uint8Array(t.pixels),e=this.player.getContext("2d",{alpha:!1}),this.player.width=t.w,this.player.height=t.h,(i=e.createImageData(t.w,t.h)).data.set(s),e.putImageData(i,0,0)}menu(){return{text:"__(Option)",nodes:[{text:"__(Camera channel)"}],onchildselect:t=>this.requestChannel()}}openSession(){if(Antunnel&&this.setting.channel)return this.tunnel=Antunnel.tunnel,this.sub=new Antunnel.Subscriber(this.setting.channel),this.sub.onopen=()=>console.log("Subscribed to camera channel"),this.sub.onerror=t=>this.error(__("Error: {0}",new TextDecoder("utf-8").decode(t.data)),t),this.sub.onctrl=t=>{switch(this.cam_setting.w=Antunnel.Msg.int_from(t.data,0),this.cam_setting.h=Antunnel.Msg.int_from(t.data,2),this.cam_setting.fps=t.data[4],this.cam_setting.quality=t.data[5],this.mute=!0,this.qctl.value=this.cam_setting.quality,`${this.cam_setting.w}x${this.cam_setting.h}`){case"320x240":this.resoctl.selected=0;break;case"640x480":this.resoctl.selected=1;break;case"800x600":this.resoctl.selected=2;break;case"1024x768":this.resoctl.selected=3;break;case"1920x1080":this.resoctl.selected=4}return this.fpsctl.selected=this.cam_setting.fps/5-1,this.mute=!1},this.sub.onmessage=t=>{if(this.decoder)return this.decoder.postMessage(t.data.buffer,[t.data.buffer])},this.sub.onclose=()=>(this.sub=void 0,this.notify(__("Unsubscribed to the camera service")),this.quit()),Antunnel.tunnel.subscribe(this.sub)}cleanup(){if(this.sub&&this.sub.close(),this.decoder)return this.decoder.terminate()}setCameraSetting(){var t;if(this.sub)return(t=new Uint8Array(6)).set(Antunnel.Msg.bytes_of(this.cam_setting.w),0),t.set(Antunnel.Msg.bytes_of(this.cam_setting.h),2),t[4]=this.cam_setting.fps,t[5]=this.cam_setting.quality,this.sub.send(Antunnel.Msg.CTRL,t)}}).singleton=!0,this.OS.register("RemoteCamera",t)}).call(this);
(function(){var t;(t=class extends this.OS.application.BaseApplication{constructor(t){super("RemoteCamera",t)}main(){var t,e,s;for(this.decoder=new Worker("pkg://RemoteCamera/decoder.js".asFileHandle().getlink()),this.decoder.onmessage=t=>this.paint(t.data),this.decoder.postMessage({cmd:0,data:"pkg://libjpeg/jpg.js".asFileHandle().getlink()}),this.mute=!1,this.player=this.find("player"),this.qctl=this.find("qctl"),this.fpsctl=this.find("fpsctl"),this.cam_setting={w:640,h:480,fps:10,quality:60},t=[],e=s=5;s<=30;e=s+=5)t.push({text:""+e,value:e});return this.fpsctl.data=t,this.fpsctl.selected=this.cam_setting.fps/5-1,this.fpsctl.onlistselect=t=>{if(!this.mute)return this.cam_setting.fps=t.data.item.data.value,this.setCameraSetting()},this.qctl.value=this.cam_setting.quality,this.resoctl=this.find("resoctl"),this.resoctl.data=[{text:__("320x240"),mode:"qvga"},{text:__("640x480"),selected:!0,mode:"vga"},{text:__("800x600"),mode:"svga"},{text:__("1024x760"),mode:"hd"},{text:__("1920×1080"),mode:"fhd"}],this.resoctl.onlistselect=t=>{if(!this.mute){switch(t.data.item.data.mode){case"qvga":this.cam_setting.w=320,this.cam_setting.h=240;break;case"vga":this.cam_setting.w=640,this.cam_setting.h=480;break;case"svga":this.cam_setting.w=800,this.cam_setting.h=600;break;case"hd":this.cam_setting.w=1024,this.cam_setting.h=768;break;case"fhd":this.cam_setting.w=1920,this.cam_setting.h=1080}return this.setCameraSetting()}},this.qctl.onvaluechange=t=>{if(!this.mute)return this.cam_setting.quality=t.data,this.setCameraSetting()},Antunnel.tunnel?this.setting.channel?this.openSession():this.requestChannel():this.notify(__("Antunnel service is not available"))}requestChannel(){return this.openDialog("PromptDialog",{title:__("Enter camera channel"),label:__("Please enter camera channel name")}).then(t=>(this.setting.channel=t,this.sub?(this.sub.onclose=t=>this.openSession(),this.sub.close()):this.openSession()))}paint(t){var e,s,i;return s=new Uint8Array(t.pixels),e=this.player.getContext("2d",{alpha:!1}),this.player.width=t.w,this.player.height=t.h,(i=e.createImageData(t.w,t.h)).data.set(s),e.putImageData(i,0,0)}menu(){return{text:"__(Option)",nodes:[{text:"__(Camera channel)"}],onchildselect:t=>this.requestChannel()}}openSession(){if(Antunnel&&this.setting.channel)return this.tunnel=Antunnel.tunnel,this.sub=new Antunnel.Subscriber(this.setting.channel),this.sub.onopen=()=>console.log("Subscribed to camera channel"),this.sub.onerror=t=>this.error(__("Error: {0}",new TextDecoder("utf-8").decode(t.data)),t),this.sub.onctrl=t=>{switch(this.cam_setting.w=Antunnel.Msg.int_from(t.data,0),this.cam_setting.h=Antunnel.Msg.int_from(t.data,2),this.cam_setting.fps=t.data[4],this.cam_setting.quality=t.data[5],this.mute=!0,this.qctl.value=this.cam_setting.quality,`${this.cam_setting.w}x${this.cam_setting.h}`){case"320x240":this.resoctl.selected=0;break;case"640x480":this.resoctl.selected=1;break;case"800x600":this.resoctl.selected=2;break;case"1024x768":this.resoctl.selected=3;break;case"1920x1080":this.resoctl.selected=4}return this.fpsctl.selected=this.cam_setting.fps/5-1,this.mute=!1},this.sub.onmessage=t=>{var e;if(this.decoder)return e={cmd:1,data:t.data.buffer},this.decoder.postMessage(e,[e.data])},this.sub.onclose=()=>(this.sub=void 0,this.notify(__("Unsubscribed to the camera service")),this.quit()),Antunnel.tunnel.subscribe(this.sub)}cleanup(){if(this.sub&&this.sub.close(),this.decoder)return this.decoder.terminate()}setCameraSetting(){var t;if(this.sub)return(t=new Uint8Array(6)).set(Antunnel.Msg.bytes_of(this.cam_setting.w),0),t.set(Antunnel.Msg.bytes_of(this.cam_setting.h),2),t[4]=this.cam_setting.fps,t[5]=this.cam_setting.quality,this.sub.send(Antunnel.Msg.CTRL,t)}}).singleton=!0,this.OS.register("RemoteCamera",t)}).call(this);

View File

@ -7,7 +7,7 @@
"author": "",
"email": ""
},
"version":"0.1.2-a",
"version":"0.1.3-a",
"category":"Other",
"iconclass":"fa fa-camera",
"mimes":["none"],

View File

@ -9,7 +9,7 @@ class RemoteCamera extends this.OS.application.BaseApplication
@decoder.onmessage = (e) =>
@paint e.data
@decoder.postMessage {libjpeg: "pkg://libjpeg/jpg.js".asFileHandle().getlink()}
@decoder.postMessage {cmd:0x0 ,data: "pkg://libjpeg/jpg.js".asFileHandle().getlink()}
@mute = false
@player = @find "player"
@ -166,7 +166,11 @@ class RemoteCamera extends this.OS.application.BaseApplication
@sub.onmessage = (e) =>
return unless @decoder
@decoder.postMessage e.data.buffer, [e.data.buffer]
msg = {
cmd: 0x1,
data: e.data.buffer
}
@decoder.postMessage msg, [msg.data]
@sub.onclose = () =>
@sub = undefined

View File

@ -31,12 +31,14 @@ decode = (arr) =>
}
onmessage = (e) => {
if(e.data.libjpeg)
{
importScripts(e.data.libjpeg);
}
else
{
decode(e.data);
switch (e.data.cmd) {
case 0x0:
importScripts(e.data.data);
break;
case 0x1:
decode(e.data.data);
break;
default:
console.error("Unknown command " + e.data.cmd);
}
}

View File

@ -7,7 +7,7 @@
"author": "",
"email": ""
},
"version":"0.1.2-a",
"version":"0.1.3-a",
"category":"Other",
"iconclass":"fa fa-camera",
"mimes":["none"],

View File

@ -205,7 +205,7 @@
"description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/RemoteCamera/README.md",
"category": "Other",
"author": "",
"version": "0.1.2-a",
"version": "0.1.3-a",
"dependencies": ["libjpeg@0.1.1-a","Antunnel@0.1.8-a"],
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/RemoteCamera/build/release/RemoteCamera.zip"
},