|
@@ -0,0 +1,402 @@
|
|
|
+#include <QCoreApplication>
|
|
|
+
|
|
|
+#include <QMutex>
|
|
|
+#include <iostream>
|
|
|
+#include <QFile>
|
|
|
+
|
|
|
+#include "xmlparam.h"
|
|
|
+#include "modulecomm.h"
|
|
|
+
|
|
|
+#include "rawpic.pb.h"
|
|
|
+
|
|
|
+#include "CivetServer.h"
|
|
|
+#include <cstring>
|
|
|
+
|
|
|
+#include <mutex>
|
|
|
+
|
|
|
+#ifdef _WIN32
|
|
|
+#include <windows.h>
|
|
|
+#else
|
|
|
+#include <unistd.h>
|
|
|
+#endif
|
|
|
+
|
|
|
+#include "ivh264framedecode.h"
|
|
|
+
|
|
|
+ivh264framedecode * gph264decode;
|
|
|
+
|
|
|
+class WebSocketHandler;
|
|
|
+
|
|
|
+WebSocketHandler * gpwsh264front;
|
|
|
+
|
|
|
+
|
|
|
+iv::vision::rawpic mRawPic;
|
|
|
+QMutex gMutex;
|
|
|
+qint64 gLastUpdate = 0;
|
|
|
+void * gpa;
|
|
|
+
|
|
|
+//#define DOCUMENT_ROOT "./frontend/dist"
|
|
|
+#define DOCUMENT_ROOT "./frontend"
|
|
|
+#define PORT "8081"
|
|
|
+
|
|
|
+void Listenpic(const char * strdata,const unsigned int nSize,const unsigned int index,const QDateTime * dt,const char * strmemname)
|
|
|
+{
|
|
|
+ if(nSize<1000)return;
|
|
|
+ iv::vision::rawpic pic;
|
|
|
+ if(false == pic.ParseFromArray(strdata,nSize))
|
|
|
+ {
|
|
|
+ std::cout<<"picview Listenpic fail."<<std::endl;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ gMutex.lock();
|
|
|
+ mRawPic.CopyFrom(pic);
|
|
|
+ gMutex.unlock();
|
|
|
+ gLastUpdate = QDateTime::currentMSecsSinceEpoch();
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+QMutex gMutexpic;
|
|
|
+std::shared_ptr<char> gpstr_pic;
|
|
|
+int gpicsize;
|
|
|
+bool gbpicupdate = false;
|
|
|
+
|
|
|
+void threadgetpic()
|
|
|
+{
|
|
|
+ while(1)
|
|
|
+ {
|
|
|
+ int nindex = gph264decode->GetUpdatedIndex(10);
|
|
|
+ if(nindex<0)continue;
|
|
|
+// std::cout<<" recv a yuv."<<std::endl;
|
|
|
+ iv::framedecodebuf * pbuf = gph264decode->LockReadBuff(nindex);
|
|
|
+ int cy = pbuf->frameheight;
|
|
|
+ int cx = pbuf->framewidth;
|
|
|
+ cv::Mat rgbImg(cy, cx,CV_8UC3);
|
|
|
+ cv::cvtColor(pbuf->myuvImg, rgbImg, CV_YUV2BGR_I420);
|
|
|
+ gph264decode->UnlockReadBuff(nindex);
|
|
|
+ std::vector<int> param = std::vector<int>(2);
|
|
|
+ param[0] = CV_IMWRITE_JPEG_QUALITY;
|
|
|
+ param[1] = 95; // default(95) 0-100
|
|
|
+ std::vector<unsigned char> buff;
|
|
|
+ int64 time1 = std::chrono::system_clock::now().time_since_epoch().count();
|
|
|
+ cv::imencode(".jpg", rgbImg, buff, param);
|
|
|
+
|
|
|
+
|
|
|
+ int64 time2 = std::chrono::system_clock::now().time_since_epoch().count();
|
|
|
+ std::cout<<" jpg compress time : "<<(time2-time1)/1000000<<std::endl;
|
|
|
+// cv::imencode(".jpg", matcompress, buff, param);
|
|
|
+ std::shared_ptr<char> pstr_ptr = std::shared_ptr<char>(new char[buff.size()]);
|
|
|
+ memcpy(pstr_ptr.get(),buff.data(),buff.size());
|
|
|
+ gMutexpic.lock();
|
|
|
+ gpstr_pic = pstr_ptr;
|
|
|
+ gpicsize = buff.size();
|
|
|
+ gbpicupdate = true;
|
|
|
+ gMutexpic.unlock();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class WsStartHandler : public CivetHandler
|
|
|
+{
|
|
|
+ public:
|
|
|
+ bool
|
|
|
+ handleGet(CivetServer *server, struct mg_connection *conn)
|
|
|
+ {
|
|
|
+
|
|
|
+ mg_printf(conn,
|
|
|
+ "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
|
|
|
+ "close\r\n\r\n");
|
|
|
+
|
|
|
+ mg_printf(conn, "<!DOCTYPE html>\n");
|
|
|
+ mg_printf(conn, "<html>\n<head>\n");
|
|
|
+ mg_printf(conn, "<meta charset=\"UTF-8\">\n");
|
|
|
+ mg_printf(conn, "<title>ADC IV Web UI</title>\n");
|
|
|
+
|
|
|
+ QFile xFile;
|
|
|
+ xFile.setFileName("./frontend/indexpic.html");
|
|
|
+ if(xFile.open(QIODevice::ReadOnly))
|
|
|
+ {
|
|
|
+ QByteArray ba = xFile.readAll();
|
|
|
+ mg_printf(conn,ba.data());
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return 1;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+class PlayHandler : public CivetHandler
|
|
|
+{
|
|
|
+ public:
|
|
|
+ bool
|
|
|
+ handleGet(CivetServer *server, struct mg_connection *conn)
|
|
|
+ {
|
|
|
+ std::cout<<" play2 handler."<<std::endl;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+//QMutex gMutexpic;
|
|
|
+//std::shared_ptr<char> gpstr_pic;
|
|
|
+//int gpicsize;
|
|
|
+//bool gbpicupdate = false;
|
|
|
+class PicHandler : public CivetHandler
|
|
|
+{
|
|
|
+ public:
|
|
|
+ bool
|
|
|
+ handleGet(CivetServer *server, struct mg_connection *conn)
|
|
|
+ {
|
|
|
+
|
|
|
+ static int ncount;
|
|
|
+ // return false;
|
|
|
+// mg_printf(conn,
|
|
|
+// "HTTP/1.1 200 OK\r\nContent-Type: "
|
|
|
+// "text/html\r\nConnection: close\r\n\r\n");
|
|
|
+// mg_printf(conn, "<html><body>");
|
|
|
+// mg_printf(conn, "<h2>This is the Pic handler!!!</h2>");
|
|
|
+// mg_printf(conn, "</body></html>\n");
|
|
|
+
|
|
|
+ mg_printf(conn,
|
|
|
+ "HTTP/1.1 200 OK\r\n"
|
|
|
+ "Connection: close\r\n"
|
|
|
+ "Max-Age: 0\r\n"
|
|
|
+ "Expires: 0\r\n"
|
|
|
+ "Cache-Control: no-cache, no-store, must-revalidate, private\r\n"
|
|
|
+ "Pragma: no-cache\r\n"
|
|
|
+ "Content-Type: multipart/x-mixed-replace; "
|
|
|
+ "boundary=--BoundaryString\r\n"
|
|
|
+ "\r\n");
|
|
|
+
|
|
|
+ mg_printf(conn,"<meta http-equiv=\"refresh\" content=\"1\">");
|
|
|
+ mg_printf(conn,
|
|
|
+ "<script type=\"text/javascript\">\r\n"
|
|
|
+ "function myrefresh() {\r\n"
|
|
|
+ "window.location.reload();\r\n"
|
|
|
+ "}\r\n"
|
|
|
+ "setTimeout('myrefresh()', 1000);\r\n"
|
|
|
+ "</script>\r\n");
|
|
|
+
|
|
|
+ QByteArray ba;
|
|
|
+
|
|
|
+ if(gbpicupdate)
|
|
|
+ {
|
|
|
+ gMutexpic.lock();
|
|
|
+ ba.append(gpstr_pic.get(),gpicsize);
|
|
|
+ gbpicupdate = false;
|
|
|
+ gMutexpic.unlock();
|
|
|
+ }
|
|
|
+// if(gLastUpdate > 0)
|
|
|
+// {
|
|
|
+// iv::vision::rawpic xrawpic;
|
|
|
+// gMutex.lock();
|
|
|
+// xrawpic.CopyFrom(mRawPic);
|
|
|
+// gMutex.unlock();
|
|
|
+// ba.append(xrawpic.picdata().data(),xrawpic.picdata().size());
|
|
|
+
|
|
|
+// }
|
|
|
+
|
|
|
+
|
|
|
+ mg_printf(conn,
|
|
|
+ "--BoundaryString\r\n"
|
|
|
+ "Content-type: image/jpeg\r\n"
|
|
|
+ "Content-Length: %zu\r\n"
|
|
|
+ "\r\n",
|
|
|
+ ba.size());
|
|
|
+
|
|
|
+
|
|
|
+ mg_write(conn, ba.data(), ba.size());
|
|
|
+
|
|
|
+
|
|
|
+ mg_printf(conn, "\r\n\r\n");
|
|
|
+
|
|
|
+
|
|
|
+ ncount++;
|
|
|
+ // printf("send pic. %d\n",ncount);
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+PicHandler * gpwspicfront;
|
|
|
+
|
|
|
+#ifdef USE_WEBSOCKET
|
|
|
+class WebSocketHandler : public CivetWebSocketHandler {
|
|
|
+
|
|
|
+
|
|
|
+ std::vector<struct mg_connection *> mvectorconn;
|
|
|
+ std::mutex mMutex;
|
|
|
+public:
|
|
|
+ void BroadData(const char * strdata,int ndata)
|
|
|
+ {
|
|
|
+ int i;
|
|
|
+ mMutex.lock();
|
|
|
+ for(i=0;i<(int)mvectorconn.size();i++)
|
|
|
+ {
|
|
|
+ std::cout<<" send frame data . size : "<<ndata<<std::endl;
|
|
|
+ mg_websocket_write(mvectorconn[i], MG_WEBSOCKET_OPCODE_BINARY, strdata, ndata);
|
|
|
+ }
|
|
|
+ mMutex.unlock();
|
|
|
+ }
|
|
|
+ int a = 1;
|
|
|
+private:
|
|
|
+ virtual bool handleConnection(CivetServer *server,
|
|
|
+ const struct mg_connection *conn) {
|
|
|
+ printf("WS connected\n");
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual void handleReadyState(CivetServer *server,
|
|
|
+ struct mg_connection *conn) {
|
|
|
+ printf("WS ready\n");
|
|
|
+
|
|
|
+ mMutex.lock();
|
|
|
+ mvectorconn.push_back(conn);
|
|
|
+ mMutex.unlock();
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual bool handleData(CivetServer *server,
|
|
|
+ struct mg_connection *conn,
|
|
|
+ int bits,
|
|
|
+ char *data,
|
|
|
+ size_t data_len) {
|
|
|
+
|
|
|
+ return true;
|
|
|
+// return (data_len<5);
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual void handleClose(CivetServer *server,
|
|
|
+ const struct mg_connection *conn) {
|
|
|
+ printf("WS closed\n");
|
|
|
+ int i;
|
|
|
+ mMutex.lock();
|
|
|
+ for(i=0;i<(int)mvectorconn.size();i++)
|
|
|
+ {
|
|
|
+ if(conn == mvectorconn[i])
|
|
|
+ {
|
|
|
+ mvectorconn.erase(mvectorconn.begin()+i);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ mMutex.unlock();
|
|
|
+ }
|
|
|
+};
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef USE_WEBSOCKET
|
|
|
+class h264picHandler : public CivetWebSocketHandler {
|
|
|
+
|
|
|
+
|
|
|
+ std::vector<struct mg_connection *> mvectorconn;
|
|
|
+ std::mutex mMutex;
|
|
|
+
|
|
|
+ virtual bool handleConnection(CivetServer *server,
|
|
|
+ const struct mg_connection *conn) {
|
|
|
+ printf("WS connected\n");
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual void handleReadyState(CivetServer *server,
|
|
|
+ struct mg_connection *conn) {
|
|
|
+ printf("WS ready\n");
|
|
|
+
|
|
|
+ mMutex.lock();
|
|
|
+ mvectorconn.push_back(conn);
|
|
|
+ mMutex.unlock();
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual bool handleData(CivetServer *server,
|
|
|
+ struct mg_connection *conn,
|
|
|
+ int bits,
|
|
|
+ char *data,
|
|
|
+ size_t data_len) {
|
|
|
+
|
|
|
+ std::cout<<" data size : "<<data_len<<std::endl;
|
|
|
+ iv::rawframedata xframe;
|
|
|
+ xframe.mpstr_ptr = std::shared_ptr<char>(new char[data_len]);
|
|
|
+ xframe.ndatasize = data_len;
|
|
|
+ memcpy(xframe.mpstr_ptr.get(),data,data_len);
|
|
|
+ gph264decode->addframedata(xframe);
|
|
|
+ return true;
|
|
|
+// return (data_len<5);
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual void handleClose(CivetServer *server,
|
|
|
+ const struct mg_connection *conn) {
|
|
|
+ printf("WS closed\n");
|
|
|
+ int i;
|
|
|
+ mMutex.lock();
|
|
|
+ for(i=0;i<(int)mvectorconn.size();i++)
|
|
|
+ {
|
|
|
+ if(conn == mvectorconn[i])
|
|
|
+ {
|
|
|
+ mvectorconn.erase(mvectorconn.begin()+i);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ mMutex.unlock();
|
|
|
+ }
|
|
|
+};
|
|
|
+#endif
|
|
|
+
|
|
|
+void Listenframe(const char * strdata,const unsigned int nSize,const unsigned int index,const QDateTime * dt,const char * strmemname)
|
|
|
+{
|
|
|
+ if(nSize<1000)return;
|
|
|
+ gpwsh264front->BroadData(strdata,nSize);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+int main(int argc, char *argv[])
|
|
|
+{
|
|
|
+ QCoreApplication a(argc, argv);
|
|
|
+
|
|
|
+ gph264decode = new ivh264framedecode(1920,1080);
|
|
|
+
|
|
|
+ std::thread * pthreadpic = new std::thread(threadgetpic);
|
|
|
+
|
|
|
+ iv::xmlparam::Xmlparam xp("./picview_civetweb.xml");
|
|
|
+ std::string strmsgname = xp.GetParam("imagemsgname","picfront");
|
|
|
+ std::string strport = xp.GetParam("Port","6123");
|
|
|
+ gpa = iv::modulecomm::RegisterRecv(strmsgname.data(),Listenpic);
|
|
|
+
|
|
|
+ void * pah264 = iv::modulecomm::RegisterRecv("h264front",Listenframe);
|
|
|
+
|
|
|
+ mg_init_library(0);
|
|
|
+
|
|
|
+
|
|
|
+ const char *options[] = {
|
|
|
+ "document_root", DOCUMENT_ROOT, "listening_ports", strport.data(), 0};
|
|
|
+
|
|
|
+ std::vector<std::string> cpp_options;
|
|
|
+ for (int i=0; i<(sizeof(options)/sizeof(options[0])-1); i++) {
|
|
|
+ cpp_options.push_back(options[i]);
|
|
|
+ }
|
|
|
+
|
|
|
+ // CivetServer server(options); // <-- C style start
|
|
|
+ CivetServer server(cpp_options); // <-- C++ style start
|
|
|
+
|
|
|
+ WsStartHandler h_ws;
|
|
|
+ server.addHandler("/", h_ws);
|
|
|
+
|
|
|
+ PicHandler h_pic;
|
|
|
+ gpwspicfront = &h_pic;
|
|
|
+ server.addHandler("/pic", h_pic);
|
|
|
+
|
|
|
+ WebSocketHandler h_wsfront;
|
|
|
+ gpwsh264front = &h_wsfront;
|
|
|
+ server.addWebSocketHandler("/h264front",h_wsfront);
|
|
|
+
|
|
|
+ h264picHandler h_wsh264picfront;
|
|
|
+ server.addWebSocketHandler("/h264picfront",h_wsh264picfront);
|
|
|
+
|
|
|
+ PlayHandler h_play;
|
|
|
+ server.addHandler("/play2", h_play);
|
|
|
+
|
|
|
+ return a.exec();
|
|
|
+}
|