Merge branch 'main' of steffen.gulpe.de:steffen/MiniWebCam

main
Steffen Pohle 4 weeks ago
commit dd5b260c17

4
.gitignore vendored

@ -0,0 +1,4 @@
*.o
miniwebcam
config.h

@ -44,6 +44,8 @@ Configuration::Configuration() {
web_height = -1; web_height = -1;
web_width = -1; web_width = -1;
web_imagerefresh = 250; web_imagerefresh = 250;
filter_ratio = 0.5;
}; };
Configuration::~Configuration() { Configuration::~Configuration() {
@ -276,3 +278,59 @@ void Configuration::Help() {
printf (" ./miniwebcam -sslkey ./ssl-key.pem -sslcert ./ssl-cert.pem -websize 800x600\n"); printf (" ./miniwebcam -sslkey ./ssl-key.pem -sslcert ./ssl-cert.pem -websize 800x600\n");
} }
void Configuration::SetValue(std::string name, std::string value) {
if (name.compare("filter_ratio") == 0) {
filter_ratio = atof(value.c_str());
debug ("Filter Ration set to : %g", filter_ratio);
}
if (name.compare("auto_birghtness") == 0) {
auto_brightness = atol(value.c_str());
debug ("Auto Brightness set to : %ld", auto_brightness);
}
if (name.compare("auto_birghtness_target") == 0) {
auto_brightness_target = atof(value.c_str());
debug ("Filter Ration set to : %g", auto_brightness_target);
}
};
std::string Configuration::GetValues() {
JSONParse jp;
JSONElement je;
je.Clear();
jp.Clear();
JSONParse jpe;
//
jpe.Clear();
jpe.AddObject("name", "filter_ratio");
jpe.AddObject("value", filter_ratio);
jpe.AddObject("desc", "Ratio between new to old image (1.0 = new image)");
je.SetAddArray("variables", jpe.ToString());
//
jpe.Clear();
jpe.AddObject("name", "auto_brightness");
jpe.AddObject("value", (int64_t) auto_brightness);
jpe.AddObject("desc", "Ctrl_ID for the brightness");
je.SetAddArray("variables", jpe.ToString());
//
jpe.Clear();
jpe.AddObject("name", "auto_brightness_target");
jpe.AddObject("value", auto_brightness_target);
jpe.AddObject("desc", "target value for auto brightness");
je.SetAddArray("variables", jpe.ToString());
//
jp.AddObject(je);
return jp.ToString();
};

@ -47,12 +47,19 @@ public:
std::string vdev_dumpfile; std::string vdev_dumpfile;
std::string vdev_dumppath; std::string vdev_dumppath;
unsigned int auto_brightness;
float auto_brightness_target;
float filter_ratio;
Configuration(); Configuration();
~Configuration(); ~Configuration();
int LoadArgs(int argc, char **argv); int LoadArgs(int argc, char **argv);
int LoadFile(std::string fn); int LoadFile(std::string fn);
void SetValue(std::string name, std::string value);
std::string GetValues();
int GetInitFlags() { return initflags; }; int GetInitFlags() { return initflags; };
std::string GetFilename() { return filename; }; std::string GetFilename() { return filename; };

@ -153,7 +153,7 @@ int Convert (ConvertData *cdata, VideoFrame *dest, VideoFrameFloat *destf, unsig
*(ptrdst++) = g; *(ptrdst++) = g;
*(ptrdst++) = b; *(ptrdst++) = b;
} }
else { if (ptrdstf) {
*(ptrdstf++) = (float)r/255.0; *(ptrdstf++) = (float)r/255.0;
*(ptrdstf++) = (float)g/255.0; *(ptrdstf++) = (float)g/255.0;
*(ptrdstf++) = (float)b/255.0; *(ptrdstf++) = (float)b/255.0;
@ -188,7 +188,7 @@ int Convert (ConvertData *cdata, VideoFrame *dest, VideoFrameFloat *destf, unsig
*(ptrdst++) = g; *(ptrdst++) = g;
*(ptrdst++) = b; *(ptrdst++) = b;
} }
else { if (ptrdstf) {
*(ptrdstf++) = (float)r/255.0; *(ptrdstf++) = (float)r/255.0;
*(ptrdstf++) = (float)g/255.0; *(ptrdstf++) = (float)g/255.0;
*(ptrdstf++) = (float)b/255.0; *(ptrdstf++) = (float)b/255.0;
@ -221,7 +221,7 @@ int Convert (ConvertData *cdata, VideoFrame *dest, VideoFrameFloat *destf, unsig
*(ptrdst++) = g; *(ptrdst++) = g;
*(ptrdst++) = b; *(ptrdst++) = b;
} }
else { if (ptrdstf) {
*(ptrdstf++) = (float)r/255.0; *(ptrdstf++) = (float)r/255.0;
*(ptrdstf++) = (float)g/255.0; *(ptrdstf++) = (float)g/255.0;
*(ptrdstf++) = (float)b/255.0; *(ptrdstf++) = (float)b/255.0;
@ -255,7 +255,7 @@ int Convert (ConvertData *cdata, VideoFrame *dest, VideoFrameFloat *destf, unsig
*(ptrdst++) = g; *(ptrdst++) = g;
*(ptrdst++) = b; *(ptrdst++) = b;
} }
else { if (ptrdstf) {
*(ptrdstf++) = (float)r/255.0; *(ptrdstf++) = (float)r/255.0;
*(ptrdstf++) = (float)g/255.0; *(ptrdstf++) = (float)g/255.0;
*(ptrdstf++) = (float)b/255.0; *(ptrdstf++) = (float)b/255.0;
@ -322,7 +322,7 @@ int Convert (ConvertData *cdata, VideoFrame *dest, VideoFrameFloat *destf, unsig
*(ptrdst++) = g; *(ptrdst++) = g;
*(ptrdst++) = b; *(ptrdst++) = b;
} }
else { if (ptrdstf) {
*(ptrdstf++) = (float)r/255.0; *(ptrdstf++) = (float)r/255.0;
*(ptrdstf++) = (float)g/255.0; *(ptrdstf++) = (float)g/255.0;
*(ptrdstf++) = (float)b/255.0; *(ptrdstf++) = (float)b/255.0;
@ -365,7 +365,7 @@ int Convert (ConvertData *cdata, VideoFrame *dest, VideoFrameFloat *destf, unsig
*(ptrdst++) = g; *(ptrdst++) = g;
*(ptrdst++) = b; *(ptrdst++) = b;
} }
else { if (ptrdstf) {
*(ptrdstf++) = (float)r/255.0; *(ptrdstf++) = (float)r/255.0;
*(ptrdstf++) = (float)g/255.0; *(ptrdstf++) = (float)g/255.0;
*(ptrdstf++) = (float)b/255.0; *(ptrdstf++) = (float)b/255.0;

@ -43,6 +43,7 @@ static void *thread_webserver(void *ignored_argument) {
static void *thread_video(void *ignored_argument) { static void *thread_video(void *ignored_argument) {
int cycle = 0;
if (config.vdev_dumpfile.length() > 0) { if (config.vdev_dumpfile.length() > 0) {
vdev = new VideoDevice_Dump(); vdev = new VideoDevice_Dump();
@ -71,9 +72,10 @@ static void *thread_video(void *ignored_argument) {
vdev->Stop(); vdev->Stop();
vdev->Start(); vdev->Start();
} }
if ((cycle++ % 2) == 0) vdev->RefreshCtrls();
Lock(); Lock();
inputimage.CopyTo(&currentimage, config.web_width, config.web_height); inputimage.CopyTo(&currentimage, config.web_width, config.web_height);
if (inputfloatfilter.AddScaledImage(&inputfloat, 0.6, 0.4) == 0) if (inputfloatfilter.AddScaledImage(&inputfloat, config.filter_ratio) == 0)
inputfloat.CopyTo(&inputfloatfilter); inputfloat.CopyTo(&inputfloatfilter);
inputfloatfilter.CopyTo(&currentimagefloat); inputfloatfilter.CopyTo(&currentimagefloat);
UnLock(); UnLock();

@ -42,3 +42,13 @@ int VideoDevice::UnLock() {
if (pthread_mutex_unlock(&mtx) == 0) return 1; if (pthread_mutex_unlock(&mtx) == 0) return 1;
else return 0; else return 0;
}; };
void VideoDevice::RefreshCtrls() {
std::list<VideoDevCtrl>::iterator i;
for (i = vidctrls.begin(); i != vidctrls.end(); i++) {
GetDevCtrl(i->id, &(i->value));
}
};

@ -88,6 +88,7 @@ class VideoDevice {
virtual int SetDevCtrl(unsigned int id, int value) { debug (""); return 0; }; virtual int SetDevCtrl(unsigned int id, int value) { debug (""); return 0; };
virtual int GetDevCtrl(unsigned int id, int *value) { debug (""); return 0; }; virtual int GetDevCtrl(unsigned int id, int *value) { debug (""); return 0; };
virtual std::list<VideoDevCtrl> GetDevCtrls() { return vidctrls; }; virtual std::list<VideoDevCtrl> GetDevCtrls() { return vidctrls; };
virtual void RefreshCtrls();
}; };
#include "videodevice_v4l2.h" #include "videodevice_v4l2.h"

@ -277,7 +277,7 @@ int VideoFrameFloat::CopyTo(VideoFrameFloat *dest) {
}; };
int VideoFrameFloat::AddScaledImage(VideoFrameFloat *vf, float f1, float f2) { int VideoFrameFloat::AddScaledImage(VideoFrameFloat *vf, float ratio) {
float *sptr, *dptr; float *sptr, *dptr;
int x, y; int x, y;
@ -285,7 +285,7 @@ int VideoFrameFloat::AddScaledImage(VideoFrameFloat *vf, float f1, float f2) {
for (dptr = memf, sptr = vf->GetPixBuf(), y = 0; y < height; y++) for (dptr = memf, sptr = vf->GetPixBuf(), y = 0; y < height; y++)
for (x = 0; x < width*3; x++) { for (x = 0; x < width*3; x++) {
*dptr = f1 * (*dptr) + f2 * (*sptr); *dptr = (1.0-ratio) * (*dptr) + ratio * (*sptr);
dptr++; dptr++;
sptr++; sptr++;
} }

@ -49,7 +49,7 @@ class VideoFrameFloat {
int CopyTo(VideoFrame *dest); int CopyTo(VideoFrame *dest);
int CopyTo(VideoFrameFloat *dest); int CopyTo(VideoFrameFloat *dest);
int AddScaledImage(VideoFrameFloat *vf, float f1, float f2); int AddScaledImage(VideoFrameFloat *vf, float ratio);
}; };

@ -10,6 +10,9 @@ extern VideoDevice *vdev;
std::string API_Get_Ctrls(); std::string API_Get_Ctrls();
std::string API_Set_Ctrl(std::string request); std::string API_Set_Ctrl(std::string request);
std::string API_Get_Values();
std::string API_Set_Value(std::string request);
// InMemoryFile GenerateJpgFile(VideoFrame *vf); // InMemoryFile GenerateJpgFile(VideoFrame *vf);
InMemoryTar assets; InMemoryTar assets;
@ -44,9 +47,20 @@ int WebCamServer::HandleRequest (WebRequestBuffer *requestbuffer, WebServerClien
if (webclient->SendResponseData(requestbuffer, API_Get_Ctrls(), "") != 1) return 0; if (webclient->SendResponseData(requestbuffer, API_Get_Ctrls(), "") != 1) return 0;
} }
else if (request.find("/set/ctrl") != std::string::npos) { else if (request.find("/set/ctrl") != std::string::npos) {
debug ("set controls"); debug ("set control");
if (webclient->SendResponseData(requestbuffer, API_Set_Ctrl(request), "") != 1) return 0; if (webclient->SendResponseData(requestbuffer, API_Set_Ctrl(request), "") != 1) return 0;
} }
else if (request.compare("/get/variables") == 0) {
debug ("get values");
if (webclient->SendResponseData(requestbuffer, API_Get_Values(), "") != 1) return 0;
}
else if (request.find("/set/var") != std::string::npos) {
debug ("set value");
if (webclient->SendResponseData(requestbuffer, API_Set_Value(request), "") != 1) return 0;
}
else if (isfile("www"+request)) { else if (isfile("www"+request)) {
if (webclient->SendResponseFile(requestbuffer, request, "") != 1) return 0; if (webclient->SendResponseFile(requestbuffer, request, "") != 1) return 0;
} }
@ -102,14 +116,56 @@ std::string API_Set_Ctrl(std::string request) {
while ((t = strchr (t, '/'))) { while ((t = strchr (t, '/'))) {
i++; i++;
t++; t++;
if (i == 3) id = atol (t); if (i == 3) {
if (i == 4) value = atoi (t); char *v = strchr (t, '=');
id = atol (t);
if (v == NULL) break;
value = atoi(++v);
debug ("id:%d value:%d", id, value);
vdev->SetDevCtrl(id, value);
break;
}
if (i > 4) break; if (i > 4) break;
} }
vdev->SetDevCtrl(id, value);
JSONParse jp; JSONParse jp;
jp.Clear(); jp.Clear();
return jp.ToString(); return jp.ToString();
} }
std::string API_Get_Values() {
return config.GetValues();
}
std::string API_Set_Value(std::string request) {
std::string name;
std::string value;
char *t = (char*) request.c_str();
int i = 0;
while ((t = strchr (t, '/'))) {
i++;
t++;
printf ("%d %s\n", i, t);
if (i == 3) {
char *v = strchr (t, '=');
if (v == NULL) break;
name = ((std::string) t).substr(0, (v-t));
value = (++v);
debug ("name:%s value:%s", name.c_str(), value.c_str());
config.SetValue(name, value);
break;
}
if (i > 4) break;
}
JSONParse jp;
jp.Clear();
return jp.ToString();
}

@ -2,3 +2,19 @@ body {
background-color: #444; background-color: #444;
color: #BBB; color: #BBB;
} }
.noborder {
border: none;
}
.withborder {
border: thin solid;
border-collapse: collapse;
}
.float {
float: left;
padding: 10px;
border: thin solid;
}

@ -7,10 +7,12 @@
<body> <body>
<div class="toggle"> <table class="noborder"><tr><td>
<label>Filter Processing<input id="floatimage" type="checkbox"><span class="slider"></span></label> <label>Filter Processing<input id="floatimage" type="checkbox"></label>
</div> </td><td>
<label>Auto Brightness<input id="autobright" type="search" list="autobrightlist"><datalist id="autobrightlist"></datalist></label>
</td></tr>
</table>
<br> <br>
<div class="webcamimage"> <div class="webcamimage">
@ -19,19 +21,26 @@
<br> <br>
<table id="controls"></table> <div class="float">
<h2>Controls</h2><hr>
<table id="controls" class="withborder"></table>
</div>
<div class="float">
<h2>Infos</h2><hr>
<table id="variables" class="withborder"></table>
</div>
<br> <br>
<div id="debug"> <div id="debug">
</div> </div>
</body> </body>
<script> <script>
let ctrls; let ctrls;
let variables;
function reloadImage() { function reloadImage() {
const img1 = document.getElementById('webcamimage'); const img1 = document.getElementById('webcamimage');
@ -44,7 +53,8 @@ function reloadImage() {
function refreshCtrls() { function refreshCtrls() {
let debug = document.getElementById("debug"); let debug = document.getElementById("debug");
let datalist = document.getElementById("autobrightlist");
datalist.innerHTML = "";
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: 'get/ctrls', url: 'get/ctrls',
@ -55,11 +65,12 @@ function refreshCtrls() {
ctrls = JSON.parse(response); ctrls = JSON.parse(response);
let table = document.getElementById("controls"); let table = document.getElementById("controls");
let t = "<thead><tr><th>Name</th><th>Min</th><th>Max</th><th>Value</th></thead><tbody>"; let t = "<thead class=\"withborder\"><tr class=\"withborder\"><th class=\"withborder\">Name</th><th class=\"withborder\">Min</th><th class=\"withborder\">Max</th><th class=\"withborder\">Value</th></thead><tbody>";
ctrls.ctrls.forEach(function (elm, idx) { ctrls.ctrls.forEach(function (elm, idx) {
t += "<tr><td>"+elm.name+"</td><td>"+elm.min+"</td>"+ t += "<tr class=\"withborder\"><td class=\"withborder\">"+elm.name+"</td><td class=\"withborder\">"+elm.min+"</td>"+
"<td>"+elm.max+"</td><td>" + "<td class=\"withborder\">"+elm.max+"</td><td class=\"withborder\">" +
"<input class=\"ctrlvalue\" dataid=\""+elm.id+"\" value=\""+elm.value+"\"></td></tr>"; "<input class=\"ctrlvalue\" dataid=\""+elm.id+"\" value=\""+elm.value+"\" size=\"6\" inputmode=\"search\"></td></tr>";
datalist.innerHTML += "<option value=\""+elm.id + " " + elm.name+"\">";
}); });
t += "</tbody>"; t += "</tbody>";
table.innerHTML = t; table.innerHTML = t;
@ -70,12 +81,43 @@ function refreshCtrls() {
}); });
} }
function refreshVariables() {
let debug = document.getElementById("debug");
$.ajax({
type: "POST",
url: 'get/variables',
data: "",
success: function(response)
{
let jsonData = {};
variables = JSON.parse(response);
let table = document.getElementById("variables");
let t = "<thead><tr class=\"withborder\"><th class=\"withborder\">Name</th><th class=\"withborder\">Value</th><th class=\"withborder\">Description</th></thead><tbody>";
variables.variables.forEach(function (elm, idx) {
t += "<tr class=\"withborder\"><td class=\"withborder\">"+elm.name+"</td>"+
"<td class=\"withborder\"><input class=\"variablevalue\" dataid=\""+elm.name+"\" value=\""+elm.value+"\" size=\"6\" inputmode=\"search\"></td>"+
"<td class=\"withborder\">"+elm.desc+"</td></tr>";
});
t += "</tbody>";
table.innerHTML = t;
},
error: function(error) {
debug.innerHTML = "ERROR";
}
});
}
function setCtrl(id, value) { function setCtrl(id, value) {
let debug = document.getElementById("debug"); let debug = document.getElementById("debug");
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: 'set/ctrl/'+id+"/"+value, url: 'set/ctrl/'+id+"="+value,
data: "", data: "",
success: function(response) success: function(response)
{ {
@ -87,8 +129,39 @@ function setCtrl(id, value) {
}); });
} }
setInterval(reloadImage, 500);
function setVariable(id, value) {
let debug = document.getElementById("debug");
$.ajax({
type: "POST",
url: 'set/var/'+id+"="+value,
data: "",
success: function(response)
{
refreshCtrls();
},
error: function(error) {
debug.innerHTML = "ERROR";
}
});
}
let cyclecnt = 0;
function refresh() {
reloadImage();
if (((cyclecnt++) % 25) == 0) {
refreshCtrls();
refreshVariables();
}
}
setInterval(refresh, 500);
refreshCtrls(); refreshCtrls();
refreshVariables();
$(document).on('keypress', '.ctrlvalue', function(e) { $(document).on('keypress', '.ctrlvalue', function(e) {
if (e.key === 'Enter' || e.keyCode === 13) { if (e.key === 'Enter' || e.keyCode === 13) {
@ -102,6 +175,18 @@ $(document).on('keypress', '.ctrlvalue', function(e) {
} }
}); });
$(document).on('keypress', '.variablevalue', function(e) {
if (e.key === 'Enter' || e.keyCode === 13) {
// Hier deine Funktion einfügen
let id = this.getAttribute('dataid');
let value = this.value;
setVariable(id, value);
// Verhindert das Standard-Verhalten (z. B. Formular absenden)
e.preventDefault();
}
});
</script> </script>
</html> </html>
Loading…
Cancel
Save