]> Zhao Yanbai Git Server - acecode.git/commitdiff
add esp32camweb
authoracevest <zhaoyanbai@126.com>
Sun, 17 Jan 2021 05:10:00 +0000 (13:10 +0800)
committeracevest <zhaoyanbai@126.com>
Sun, 17 Jan 2021 05:10:00 +0000 (13:10 +0800)
projects/esp32_video_stream/esp32cam/esp32cam.ino
projects/esp32_video_stream/esp32camweb/canvas.html [new file with mode: 0644]
projects/esp32_video_stream/esp32camweb/go.mod [new file with mode: 0644]
projects/esp32_video_stream/esp32camweb/go.sum [new file with mode: 0644]
projects/esp32_video_stream/esp32camweb/main.go [new file with mode: 0644]

index 0086a2414dc00fab63112b3ad5a70dd48c6c8801..08ccb510a801437d3c2d8055fed357002fadf075 100644 (file)
@@ -10,7 +10,7 @@ typedef struct {
   const char *pwd;
 } WiFiItem_t;
 
-const char* websockets_server_host = "10.0.0.6";
+const char* websockets_server_host = "10.0.0.10";
 const uint16_t websockets_server_port = 80;
 
 WiFiItem_t WiFiTable[] = {
diff --git a/projects/esp32_video_stream/esp32camweb/canvas.html b/projects/esp32_video_stream/esp32camweb/canvas.html
new file mode 100644 (file)
index 0000000..eb4fce0
--- /dev/null
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html lang="en" dir="ltr">
+
+<head>
+    <meta charset="utf-8">
+    <title>CANVAS VIDEO</title>
+    <style>
+        #Video {
+            border: 1px solid red;
+        }
+    </style>
+</head>
+
+<body>
+    <canvas id="Video" width="240" height="320"></canvas>
+    <pre id="FrameRate"></pre>
+    <pre id="Msg"></pre>
+
+    <script>
+        var ws;
+        var wsURL = "wss://10.0.0.10/stream";
+        var canvas = document.getElementById('Video');
+        var ctx = canvas.getContext('2d'); 
+
+        var frameCount = 0;
+        window.setInterval(function() {
+            fps = frameCount;
+            frameCount = 0;
+            var FrameRate = document.getElementById('FrameRate');
+            FrameRate.innerHTML = "当前帧率: " + fps + " fps";
+        },1000)
+
+        function Msg(...args) {
+            msg = args.join('');
+            console.log(msg);
+
+            var Msg = document.getElementById('Msg');
+            contents = Msg.innerHTML;
+            contents += msg;
+            slice = contents.split('\n').slice(-5);
+            msg = slice.join('\n')+'\n';
+            Msg.innerHTML = msg;
+        }
+    
+        function initWebsocket() {
+            ws = new WebSocket(wsURL);
+            ws.SendCmd = function(req) {
+                req = JSON.stringify(req);
+                ws.send(req);
+            }
+    
+            ws.onopen = function () {
+                Msg("websocket opened");
+            };
+    
+            ws.onerror = function (event) {
+                Msg("websocket error: " + event);
+            };
+    
+            ws.onclose = function (event) {
+                Msg("websocket closed with code: " + event.code + " reason: " + event.reason);
+            };
+    
+            ws.onmessage = function (event) {
+                imageData = event.data;
+                frameCount++;
+                Msg("frame data len: ", imageData.size);
+                var image = new Image();
+                image.src = URL.createObjectURL(imageData);
+                image.onload = () => {
+                    URL.revokeObjectURL(image.src);
+                    ctx.save();
+                    ctx.translate(120, 180);
+                    ctx.rotate(90*(Math.PI/180));
+                    ctx.translate(-180, -120);
+                    ctx.drawImage(image, 0, 0);
+                    ctx.restore();
+                }
+            };
+        }
+
+        initWebsocket();
+    </script>
+</body>
+
+</html>
diff --git a/projects/esp32_video_stream/esp32camweb/go.mod b/projects/esp32_video_stream/esp32camweb/go.mod
new file mode 100644 (file)
index 0000000..64471b9
--- /dev/null
@@ -0,0 +1,5 @@
+module esp32camweb
+
+go 1.14
+
+require github.com/gorilla/websocket v1.4.2
diff --git a/projects/esp32_video_stream/esp32camweb/go.sum b/projects/esp32_video_stream/esp32camweb/go.sum
new file mode 100644 (file)
index 0000000..85efffd
--- /dev/null
@@ -0,0 +1,2 @@
+github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
+github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
diff --git a/projects/esp32_video_stream/esp32camweb/main.go b/projects/esp32_video_stream/esp32camweb/main.go
new file mode 100644 (file)
index 0000000..18a7974
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * ------------------------------------------------------------------------
+ *   File Name: main.go
+ *      Author: Zhao Yanbai
+ *              2021-01-16 23:01:01 Saturday CST
+ * Description: none
+ * ------------------------------------------------------------------------
+ */
+
+package main
+
+import (
+       "fmt"
+       "html/template"
+       "log"
+       "net/http"
+       "time"
+
+       "github.com/gorilla/websocket"
+)
+
+var upgrader = websocket.Upgrader{
+       ReadBufferSize:  102400,
+       WriteBufferSize: 102400,
+
+       // 解决跨域问题
+       CheckOrigin: func(r *http.Request) bool {
+               return true
+       },
+}
+
+var frameChan chan []byte
+
+func init() {
+       frameChan = make(chan []byte, 32)
+}
+
+const (
+       partBOUNDARY      = "123456789000000000000987654321"
+       streamContentType = "multipart/x-mixed-replace;boundary=" + partBOUNDARY
+       streamBoundary    = "\r\n--" + partBOUNDARY + "\r\n"
+       streamPart        = "Content-Type: image/jpeg\r\nContent-Length: %d\r\n\r\n"
+)
+
+func watchHandler(w http.ResponseWriter, r *http.Request) {
+       var err error
+       w.Header().Set("Content-Type", streamContentType)
+       w.Header().Set("Access-Control-Allow-Origin", "*")
+
+       flusher, _ := w.(http.Flusher)
+
+       for i := 0; ; i++ {
+               var data []byte
+               select {
+               case data = <-frameChan:
+                       fmt.Fprintf(w, "%v", streamBoundary)
+                       fmt.Fprintf(w, streamPart, i)
+                       _, err = w.Write(data)
+                       flusher.Flush()
+                       if err != nil {
+                               break
+                       }
+               default:
+                       continue
+               }
+
+       }
+}
+
+func videoHandler(w http.ResponseWriter, r *http.Request) {
+       var err error
+       var ws *websocket.Conn
+
+       log.Printf("video\n")
+       ws, err = upgrader.Upgrade(w, r, nil)
+       if err != nil {
+               log.Printf("err: %v", err)
+               return
+       }
+
+       defer ws.Close()
+
+       for {
+               t, p, e := ws.ReadMessage()
+               log.Printf("type %v data len %v err %v", t, len(p), e)
+               if e != nil {
+                       break
+               }
+
+               if len(p) < 100 {
+                       continue
+               }
+
+               select {
+               case frameChan <- p:
+                       log.Printf("put frame")
+               default:
+                       log.Printf("drop frame")
+               }
+
+       }
+}
+
+func streamHandler(w http.ResponseWriter, r *http.Request) {
+       var err error
+       var ws *websocket.Conn
+
+       ws, err = upgrader.Upgrade(w, r, nil)
+       if err != nil {
+               log.Printf("err: %v", err)
+               return
+       }
+
+       defer ws.Close()
+
+       for {
+               var data []byte
+               select {
+               case data = <-frameChan:
+               case <-time.After(1 * time.Millisecond):
+                       continue
+               }
+
+               err = ws.WriteMessage(websocket.BinaryMessage, data)
+               if err != nil {
+                       break
+               }
+       }
+}
+
+func canvasHandler(w http.ResponseWriter, r *http.Request) {
+       tmpl := template.Must(template.ParseFiles("./canvas.html"))
+       var data = map[string]interface{}{}
+       tmpl.Execute(w, data)
+}
+
+func main() {
+       defer fmt.Println("Program Exited...")
+
+       m := http.NewServeMux()
+       m.HandleFunc("/watch", watchHandler)
+       m.HandleFunc("/video", videoHandler)
+       m.HandleFunc("/canvas", canvasHandler)
+       m.HandleFunc("/stream", streamHandler)
+       server := http.Server{
+               Addr:    ":80",
+               Handler: m,
+       }
+
+       server.ListenAndServe()
+}