diff --git a/main.cc b/main.cc index 919fb58..b121f69 100644 --- a/main.cc +++ b/main.cc @@ -11,6 +11,7 @@ int running = 1; +pthread_mutex_t mtx; static void sig_int(int); int SetupSignals(); VideoFrame inputimage; @@ -22,50 +23,59 @@ void ErrorExit(std::string text, int errorcode) { }; -int main(int argc, char **argv) { - VideoDevice *vdev= NULL; +int Lock () { + if (pthread_mutex_lock(&mtx) == 0) return 1; + else return 0; +}; - printf ("MiniWebCam:\n"); - if (SetupSignals() == 0) return 0; - config.LoadArgs (argc, argv); - config.LoadFile (config.GetFilename()); - if (config.GetInitFlags() & CONF_INITFLAGS_PRINT) { - config.PrintConfig(); - return 0; - } +int UnLock () { + if (pthread_mutex_unlock(&mtx) == 0) return 1; + else return 0; +}; - if (config.GetInitFlags() & CONF_INITFLAGS_HELP) { - config.Help(); - return 0; + +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(); + + while (running) { + webserver.Loop(); + usleep (200); } + running = 0; // force running to 0 + + webserver.Stop(); + return NULL; +}; + + + +static void *thread_video(void *ignored_argument) { + VideoDevice *vdev= NULL; + if (config.vdev_dumpfile.length() > 0) { vdev = new VideoDevice_Dump(); } else { vdev = new VideoDevice_V4L2(); } - WebCamServer webserver; - currentimage.TestScreen(1920, 1080); - - webserver.SetupPorts(config.http_port, config.https_port); - webserver.SetupSSL(config.ssl_key, config.ssl_cert); - webserver.Start(); if (vdev->SetDevice (config.vdev_device, config.vdev_width, config.vdev_height, convert_to_pixelformat(config.vdev_format)) == 0) { debug ("could not setup device.\n"); - return 0; + goto thread_video_exit; // we use goto for a better cleanup of the thread } - if (vdev->SetIOMode (config.vdev_iomode) == 0) { debug ("could not setup iomode.\n"); - return 0; + goto thread_video_exit; } - if (vdev->Start() == 0) { debug ("Error: could not start video.\n"); - return 0; + goto thread_video_exit; } currentimage.SetSize (config.web_width, config.web_height); @@ -75,15 +85,52 @@ int main(int argc, char **argv) { vdev->Stop(); vdev->Start(); } + Lock(); inputimage.CopyTo(¤timage, config.web_width, config.web_height); - - webserver.Loop(); - usleep (1000); + UnLock(); } +thread_video_exit: + running = 0; // force the other threads to stop vdev->Stop(); - webserver.Stop(); + delete vdev; + vdev = NULL; + return NULL; +} + + + +int main(int argc, char **argv) { + pthread_t thr_webserver; + pthread_t thr_video; + + printf ("MiniWebCam:\n"); + + // prepare signals, mutex and test output image + if (SetupSignals() == 0) return 0; + pthread_mutex_init(&mtx, NULL); + currentimage.TestScreen(1920, 1080); + + // read and setup config + config.LoadArgs (argc, argv); + config.LoadFile (config.GetFilename()); + if (config.GetInitFlags() & CONF_INITFLAGS_PRINT) { + config.PrintConfig(); + return 0; + } + if (config.GetInitFlags() & CONF_INITFLAGS_HELP) { + config.Help(); + return 0; + } + + pthread_create(&thr_webserver, NULL, &thread_webserver, NULL); + pthread_create(&thr_video, NULL, &thread_video, NULL); + + while (running) { + usleep (1000); + } + return 0; }; diff --git a/miniwebcam.h b/miniwebcam.h index bbbdf6d..4d4023c 100644 --- a/miniwebcam.h +++ b/miniwebcam.h @@ -23,6 +23,8 @@ class WebCamServer : public WebServer { void ErrorExit(std::string text, int errorcode); +int Lock(); +int UnLock(); extern VideoFrame currentimage; diff --git a/webserver.cc b/webserver.cc index ad9b21d..55dd5d3 100644 --- a/webserver.cc +++ b/webserver.cc @@ -23,7 +23,9 @@ int WebCamServer::HandleRequest (WebRequestBuffer *requestbuffer, WebServerClien } else if (request.find("/snapshot.jpg") != std::string::npos) { InMemoryFile jpgfile; + Lock(); currentimage.ConvertToJpeg(&jpgfile, 99); + UnLock(); if (webclient->SendResponseFileFromMemory(requestbuffer, request, "", (void*) jpgfile.mem, jpgfile.memsize) != 1) return 0;