Browse Source

add h264view_civetweb.

yuchuli 3 years ago
parent
commit
e696c1874d

BIN
doc/工具/远程驾驶方案总结.pptx


+ 3 - 0
src/driver/driver_h264_usbimx291/driver_h264_usbimx291.pro

@@ -32,3 +32,6 @@ HEADERS += \
 !include(../../../include/common.pri ) {
     error( "Couldn't find the common.pri file!" )
 }
+
+
+#DEFINES += TEST_SAVEH264

+ 19 - 0
src/driver/driver_h264_usbimx291/main.cpp

@@ -14,6 +14,14 @@ bool gbrun = true;
 
 #include <QDateTime>
 
+#ifdef TEST_SAVEH264
+#include <QFile>
+
+QFile gFile;
+
+
+#endif
+
 void ThreadGetData()
 {
     while(gbrun)
@@ -25,6 +33,11 @@ void ThreadGetData()
             recvtime = recvtime/1000;
             double frecvtime = recvtime;
             frecvtime = frecvtime/1000000.0;
+
+#ifdef  TEST_SAVEH264
+            gFile.write(xframe.mpstr_ptr.get(),xframe.mdatalen);
+            gFile.flush();
+#endif
 //            qDebug(" recvtime : %13.6f  datatime:%13.6f",frecvtime,xframe.mfrecvtime);
             iv::modulecomm::ModuleSendMsg(gpa,xframe.mpstr_ptr.get(),xframe.mdatalen);
 
@@ -56,6 +69,12 @@ int main(int argc, char *argv[])
         strxmlpath = argv[1];
     }
 
+#ifdef TEST_SAVEH264
+
+    gFile.setFileName("/home/yuchuli/imx291.h264");
+    gFile.open(QIODevice::ReadWrite);
+#endif
+
     iv::xmlparam::Xmlparam xp(strxmlpath);
     std::string strdevname =  xp.GetParam("devname","/dev/video5");
     int nwidth = xp.GetParam("width",1920);

+ 73 - 0
src/tool/h264view_civetweb/.gitignore

@@ -0,0 +1,73 @@
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+

+ 11 - 0
src/tool/h264view_civetweb/Readme.md

@@ -0,0 +1,11 @@
+
+# 1.介绍
+这是一个使用网页查看共享内存内图片数据的程序,不需要opencv支持,只支持jpg图片。
+使用方法 http://ip:port, 例如http://192.168.1.102:6123
+
+# 2.xml参数说明
+imagemsgname rawpic格式的共享内存名称,默认值picfront
+Port 端口,默认6123
+
+# 3.运行说明
+在程序运行目录需要一个frontend的文件夹,可以从picview_civetweb目录拷贝过去,里面包含了一个名为indexpic.html的文件。

+ 137 - 0
src/tool/h264view_civetweb/frontend/indexpic.html

@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<title>ADCIV WEB UI. Designed Base CivetWeb.</title>
+<script>
+
+//var i_width=window.document.body.clientWidth//网页可用宽度  
+//var i_height=window.document.body.clientHeight;
+//var pic = document.getElementById("myCanvas");
+//pic.style.height=i_height+"px";
+//pic.style.width=i_width+"px";
+var index=0
+var xc=0
+var ic=0;
+var h264picstate = 0;
+//var int=self.setInterval('clock()',100);
+var int2=self.setInterval('changeImage()',29);
+
+	var n = 0;
+	var image=new Image();//放入函数里面:浏览器运行一分钟左右系统内存用到高达90%,故做一个全局的反冲图片
+		var strh264front = "ws://127.0.0.1:6123/h264front";
+		var strh264picfront = "ws://127.0.0.1:6123/h264picfront";
+		// Setup the WebSocket connection and start the player
+		var clienth264front = new WebSocket( strh264front );
+		var clienth264picfront = new WebSocket( strh264picfront );
+		
+		
+   	clienth264front.binaryType = 'arraybuffer';
+   	
+        clienth264front.onopen = function(evt) { 
+		
+ //           onOpen(evt) 
+        }; 
+        clienth264front.onclose = function(evt) { 
+		
+ //           onClose(evt) 
+        }; 
+        clienth264front.onmessage = function(evt) { 
+		if(h264picstate == 1)clienth264picfront.send(evt.data);   //使用websocket发送frame数据到解码服务
+ //           onMessage(evt) 
+        }; 
+        clienth264front.onerror = function(evt) { 
+ //           onError(evt) 
+        }; 
+
+        clienth264picfront.onopen = function(evt) { 
+		h264picstate = 1;
+ //           onOpen(evt) 
+        }; 
+        clienth264picfront.onclose = function(evt) { 
+		h264picstate = 0;
+ //           onClose(evt) 
+        }; 
+        clienth264picfront.onmessage = function(evt) { 
+ //           onMessage(evt) 
+        }; 
+        clienth264picfront.onerror = function(evt) { 
+ //           onError(evt) 
+        }; 
+
+
+	function changeImage()
+	{ 
+
+		var canvas=document.getElementById("myCanvas2");  
+		var cxt=canvas.getContext("2d");
+
+		//ctx.restore();
+		image.src="./pic?"+n;
+		n++; 
+		var nerror = 0;
+		
+		image.onload = function () //确保图片已经加载完毕  
+		{  
+			if (image.complete)//如果图片加载完成,绘制
+			{
+				cxt.save();
+				imgScale = 1.0;
+				CanvasWidth = 960*(1920-40)/1920;
+				CanvasHeight = 540*(1920-40)/1920;
+
+				cxt.drawImage(image,0,0,image.width,image.height,0,0,1280,720); 
+				cxt.restore();
+				nerror = 0;
+				upcount++;
+			}
+			else
+			{
+				nerror++;
+				if(nerror>100)
+				{
+					alert(image.complete);
+					nerror = 0;
+				}
+			}
+			ic = 0;
+			
+		}  
+		image.onerror=function(){  
+			document.getElementById("F2").innerHTML="error N:"+n; 
+			ic = 0;
+		};  
+		//ctx.save();
+  	}
+
+function clock() 
+{ 
+	if(ic == 0)
+	{
+		ic = 1;
+		changeImage();
+	}
+} 
+function load() {
+	changeImage();
+}
+
+
+
+</script>
+</head>
+<body onload="changeImage()">
+<!-- <div id='websock_text_field'>No websocket connection yet</div>-->
+<!--  <iframe id='image' src="" width="800" height="600"></iframe>  -->
+
+<form>
+<br>
+
+<canvas id="myCanvas2" width="1280" height="720" style="border:0px solid #c3c3c3;">  
+Your browser does not support the canvas element.  
+</canvas>
+
+<p id="demo">This is a paragraph.</p> 
+
+</body>
+</html>

+ 75 - 0
src/tool/h264view_civetweb/h264view_civetweb.pro

@@ -0,0 +1,75 @@
+QT -= gui
+
+CONFIG += c++11 console
+CONFIG -= app_bundle
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
+
+SOURCES += \
+        ../../../thirdpartylib/civetweb/CivetServer.cpp \
+        ../../../thirdpartylib/civetweb/civetweb.c \
+        ../../include/msgtype/rawpic.pb.cc \
+        main.cpp \
+    ../../driver/driver_h264_dec/ivh264framedecode.cpp
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += $$PWD/../../../thirdpartylib/civetweb
+
+INCLUDEPATH += $$PWD/../../include/msgtype
+
+
+LIBS += -lprotobuf
+
+!include(../../../include/common.pri ) {
+    error( "Couldn't find the common.pri file!" )
+}
+
+HEADERS += \
+    ../../../thirdpartylib/civetweb/CivetServer.h \
+    ../../../thirdpartylib/civetweb/civetweb.h \
+    ../../include/msgtype/rawpic.pb.h \
+    ../../driver/driver_h264_dec/ivh264framedecode.h
+
+DEFINES += NO_SSL
+#DEFINES += NO_SSL_DL
+DEFINES += USE_WEBSOCKET
+
+INCLUDEPATH += $$PWD/../../driver/driver_h264_dec
+
+LIBS += -ldl -lrt
+
+
+#DEFINES += USE_QSV
+
+LIBS += -lopencv_highgui -lopencv_core -lopencv_imgproc -lopencv_imgcodecs -lopencv_video  -lopencv_videoio -lpthread #-lopencv_shape
+
+if(contains(DEFINES,USE_QSV)){
+INCLUDEPATH += /usr/local/include
+INCLUDEPATH += /opt/intel/mediasdk/include
+LIBS += /opt/intel/mediasdk/lib/libmfx.so.1
+LIBS += -L/opt/intel/mediasdk/lib -lmfx
+LIBS += /home/yuchuli/File1/git/ffmpeg/lib/libavcodec.so.59
+LIBS += /home/yuchuli/File1/git/ffmpeg/lib/libavutil.so.57
+LIBS += /home/yuchuli/File1/git/ffmpeg/lib/libavdevice.so.59
+LIBS += /home/yuchuli/File1/git/ffmpeg/lib/libavformat.so.59
+
+
+} else {
+
+INCLUDEPATH += /usr/include/x86_64-linux-gnu
+LIBS +=  -lavcodec -lavformat -lavutil
+}
+

+ 402 - 0
src/tool/h264view_civetweb/main.cpp

@@ -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();
+}

+ 6 - 0
src/tool/h264view_civetweb/picview_civetweb.xml

@@ -0,0 +1,6 @@
+<xml>	
+	<node name="picview_civetweb">
+		<param name="imagemsgname" value="image00" />
+		<param name="Port" value="6123" />
+	</node>
+</xml>