diff --git a/Makefile b/Makefile index b0f73df..de4c6d3 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ DATAPREFIX=/var/lib RUNPID=/var/run/miniwebcam.pid ETCPREFIX=/etc DEFAULT_SERVERPORT=20010 - +ARCH=$(shell uname -m) CXX=g++ CXXFLAGS= -ggdb -fPIC -Wall -std=c++11 -I/usr/local/include LDFLAGS= -lUDPTCPNetwork -L/usr/local/lib -ljpeg -larchive @@ -19,9 +19,13 @@ all: dep miniwebcam assets.obj: tar cvf assets.tar www/* -# objcopy -I binary assets.tar assets.obj +ifeq ($(ARCH), x86_64) + objcopy -I binary -O elf64-x86-64 -B i386:x86-64 assets.tar assets.obj +else ifeq ($(ARCH), aarch64) objcopy -I binary -O elf64-littleaarch64 -B aarch64 assets.tar assets.obj -# objcopy -I binary -O elf64-x86-64 -B i386:x86-64 assets.tar assets.obj +else + $(error Unbekannte Architektur: $(ARCH)) +endif rm -rf assets.tar miniwebcam: $(OBJFILES) assets.obj diff --git a/main.cc b/main.cc index b453836..1236689 100644 --- a/main.cc +++ b/main.cc @@ -21,11 +21,11 @@ VideoFrameFloat inputfloat; VideoFrameFloat inputfloatfilter; VideoFrame currentimage; VideoFrame currentimagefloat; +VideoDevice *vdev= NULL; static void *thread_webserver(void *ignored_argument) { WebCamServer webserver; - webserver.SetupPorts(config.http_port, config.https_port); webserver.SetupSSL(config.ssl_key, config.ssl_cert); webserver.Start(); @@ -43,7 +43,6 @@ static void *thread_webserver(void *ignored_argument) { static void *thread_video(void *ignored_argument) { - VideoDevice *vdev= NULL; if (config.vdev_dumpfile.length() > 0) { vdev = new VideoDevice_Dump(); diff --git a/video.cc b/video.cc index a71621f..520fb04 100644 --- a/video.cc +++ b/video.cc @@ -24,6 +24,7 @@ VideoDevice::VideoDevice() { debug (""); + pthread_mutex_init(&mtx, NULL); }; @@ -32,3 +33,12 @@ VideoDevice::~VideoDevice() { }; +int VideoDevice::Lock() { + if (pthread_mutex_lock(&mtx) == 0) return 1; + else return 0; +}; + +int VideoDevice::UnLock() { + if (pthread_mutex_unlock(&mtx) == 0) return 1; + else return 0; +}; diff --git a/video.h b/video.h index 997a0ca..e375479 100644 --- a/video.h +++ b/video.h @@ -65,6 +65,7 @@ struct { class VideoDevice { private: protected: + pthread_mutex_t mtx; std::list vidctrls; std::string conf_videodev; std::string conf_videocdev; @@ -73,6 +74,8 @@ class VideoDevice { int conf_height; int conf_iomode; ConvertData cdata; + int Lock(); + int UnLock(); public: VideoDevice(); virtual ~VideoDevice(); @@ -84,6 +87,7 @@ class VideoDevice { virtual int GetFrame (VideoFrame *destframe, VideoFrameFloat *destfloat) { 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 std::list GetDevCtrls() { Lock(); return vidctrls; UnLock(); }; }; #include "videodevice_v4l2.h" diff --git a/videodevice_dump.cc b/videodevice_dump.cc index ccb8289..62eb93a 100644 --- a/videodevice_dump.cc +++ b/videodevice_dump.cc @@ -114,6 +114,7 @@ VideoDevice_Dump::VideoDevice_Dump() { inframe_maxsize = 0; inframe_nexttime = 0; fixedframesize = 0; + pthread_mutex_init(&mtx, NULL); }; diff --git a/videodevice_v4l2.cc b/videodevice_v4l2.cc index 22f9f3b..4a4a111 100644 --- a/videodevice_v4l2.cc +++ b/videodevice_v4l2.cc @@ -13,6 +13,7 @@ VideoDevice_V4L2::VideoDevice_V4L2() { conf_videofmt = 0; fd = -1; cfd = -1; + pthread_mutex_init(&mtx, NULL); }; @@ -72,11 +73,12 @@ int VideoDevice_V4L2::Open() { if (fd != -1) return 0; if (cfd != -1) return 0; + Lock(); // // open device and get device name and capabilities | O_NONBLOCK if((fd = open(conf_videodev.c_str(), O_RDWR)) == -1){ debug ("could not open device error: %s", strerror(errno)); - return 0; + goto v4l2_open_error; } // @@ -84,7 +86,7 @@ int VideoDevice_V4L2::Open() { if (conf_videocdev.length() > 0) { if((cfd = open(conf_videocdev.c_str(), O_RDWR)) == -1){ debug ("could not open ctrl device error: %s", strerror(errno)); - return 0; + goto v4l2_open_error; } } @@ -99,8 +101,8 @@ int VideoDevice_V4L2::Open() { if (!(vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { debug ("Error: device has no video capture capabilities"); - return 0; Close(); + goto v4l2_open_error; } // @@ -120,7 +122,9 @@ int VideoDevice_V4L2::Open() { vctl.max = queryctrl.maximum; debug ("CTRL: id:%p name:%s range:%d %d step:%d type:%d", queryctrl.id, queryctrl.name, queryctrl.minimum, queryctrl.maximum, queryctrl.step, queryctrl.type); + UnLock(); GetDevCtrl(queryctrl.id, &vctl.value); + Lock(); vidctrls.push_back(vctl); } } @@ -166,7 +170,7 @@ int VideoDevice_V4L2::Open() { close (cfd); cfd = -1; } - return 0; + goto v4l2_open_error; } // Note VIDIOC_S_FMT may change width and height. @@ -200,14 +204,19 @@ int VideoDevice_V4L2::Open() { break; } + UnLock(); return 1; + +v4l2_open_error: + UnLock(); + return 0; }; int VideoDevice_V4L2::InitMMap() { struct v4l2_requestbuffers bufreq; struct v4l2_buffer bufinfo; - printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + debug (""); int i; @@ -258,13 +267,13 @@ int VideoDevice_V4L2::InitMMap() { int VideoDevice_V4L2::Close() { printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); - + Lock(); if (fd >= 0) { UnInit(); close (fd); fd = -1; } - + UnLock(); return 1; }; @@ -316,6 +325,7 @@ int VideoDevice_V4L2::Start() { return 0; } + Lock(); switch (conf_iomode) { case IOMODE_READ: /* Nothing to do. */ @@ -332,6 +342,7 @@ int VideoDevice_V4L2::Start() { if (-1 == xioctl(fd, VIDIOC_QBUF, &buf)) { debug ("error on VIDIOC_QBUF %s", strerror(errno)); + UnLock(); return 0; } } @@ -340,17 +351,19 @@ int VideoDevice_V4L2::Start() { type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (-1 == xioctl(fd, VIDIOC_STREAMON, &type)) { debug ("VIDIOC_STREAMON %s", strerror(errno)); + UnLock(); return 0; } break; default: debug ("wrong IOMODE?"); + UnLock(); return 0; } + UnLock(); ConvertStart(&cdata, fmt.fmt.pix.pixelformat); - return 1; }; @@ -360,6 +373,8 @@ int VideoDevice_V4L2::Stop() { printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); ConvertStop(&cdata, fmt.fmt.pix.pixelformat); + Lock(); + switch (conf_iomode) { case IOMODE_READ: /* Nothing to do. */ @@ -368,13 +383,17 @@ int VideoDevice_V4L2::Stop() { type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (-1 == xioctl(fd, VIDIOC_STREAMOFF, &type)) { fprintf(stderr, "%s:%d VIDIOC_STREAMOFF Error:%s\n", __FILE__, __LINE__, strerror(errno)); + UnLock(); return 0; } break; default: printf ("%s:%d %s wrong IOMODE?\n", __FILE__, __LINE__, __FUNCTION__); + UnLock(); return 0; } + UnLock(); + Close(); return 1; }; @@ -382,13 +401,17 @@ int VideoDevice_V4L2::Stop() { int VideoDevice_V4L2::GetFrame(VideoFrame *destframe, VideoFrameFloat *destfloat) { struct v4l2_buffer buf; - int len; + int len, ret; if (destframe == NULL && destfloat == NULL) return 0; switch (conf_iomode) { case IOMODE_READ: - if ((len = read (fd, inbuffer[0].data, fmt.fmt.pix.sizeimage)) == -1) { + Lock(); + len = read (fd, inbuffer[0].data, fmt.fmt.pix.sizeimage); + UnLock(); + + if (len == -1) { switch (errno) { case EAGAIN: return -1; @@ -410,7 +433,10 @@ int VideoDevice_V4L2::GetFrame(VideoFrame *destframe, VideoFrameFloat *destfloat buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; - if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) { + Lock(); + ret = xioctl(fd, VIDIOC_DQBUF, &buf); + UnLock(); + if (ret == -1) { switch (errno) { case EAGAIN: return -1; @@ -429,8 +455,11 @@ int VideoDevice_V4L2::GetFrame(VideoFrame *destframe, VideoFrameFloat *destfloat Convert(&cdata, destframe, destfloat, inbuffer[buf.index].data, buf.bytesused, fmt.fmt.pix.pixelformat, fmt.fmt.pix.width, fmt.fmt.pix.height); } + Lock(); + ret = xioctl(fd, VIDIOC_QBUF, &buf); + UnLock(); - if (-1 == xioctl(fd, VIDIOC_QBUF, &buf)) { + if (ret == -1) { debug ("error on VIDIOC_QBUF %s", strerror(errno)); return 0; } @@ -467,11 +496,15 @@ int VideoDevice_V4L2::xioctl(int fd, int request, void *arg) { int VideoDevice_V4L2::SetDevCtrl(unsigned int id, int value) { struct v4l2_control ctrl; + int ret; CLEAR(ctrl); ctrl.id = id; ctrl.value = value; - if (-1 == xioctl (cfd != -1 ? cfd : fd, VIDIOC_S_CTRL, &ctrl)) { + Lock(); + ret = xioctl (cfd != -1 ? cfd : fd, VIDIOC_S_CTRL, &ctrl); + UnLock(); + if (-1 == ret) { return 0; } @@ -481,10 +514,14 @@ int VideoDevice_V4L2::SetDevCtrl(unsigned int id, int value) { int VideoDevice_V4L2::GetDevCtrl(unsigned int id, int *value) { struct v4l2_control ctrl; + int ret; CLEAR(ctrl); ctrl.id = id; - if (-1 == xioctl (cfd != -1 ? cfd : fd, VIDIOC_G_CTRL, &ctrl)) { + Lock(); + ret = xioctl (cfd != -1 ? cfd : fd, VIDIOC_G_CTRL, &ctrl); + UnLock(); + if (-1 == ret) { return 0; } *value = ctrl.value; diff --git a/webserver.cc b/webserver.cc index 57d31e2..c2cc442 100644 --- a/webserver.cc +++ b/webserver.cc @@ -5,6 +5,8 @@ #include "UDPTCPNetwork.h" #include "inmemorytar.h" +extern VideoDevice *vdev; + // InMemoryFile GenerateJpgFile(VideoFrame *vf); InMemoryTar assets; @@ -34,6 +36,10 @@ int WebCamServer::HandleRequest (WebRequestBuffer *requestbuffer, WebServerClien (void*) jpgfile.mem, jpgfile.memsize) != 1) return 0; } + else if (request.compare("/get/ctrls") == 0) { + std::list list; + list = vdev->GetDevCtrls(); + } else if (isfile("www"+request)) { if (webclient->SendResponseFile(requestbuffer, request, "") != 1) return 0; } diff --git a/www/index.html b/www/index.html index 221e5f6..423f1f7 100644 --- a/www/index.html +++ b/www/index.html @@ -35,7 +35,7 @@ function reloadImage() { img1.src = src1; } -setInterval(reloadImage, 250); +setInterval(reloadImage, 500);