Compare commits

...

4 Commits

Author SHA1 Message Date
langhuihui
eb633d2566 doc: update readme 2025-09-16 19:12:07 +08:00
langhuihui
af467e964e fix: add test video to docker 2025-09-16 14:30:56 +08:00
yangjinxing123
b1cb41a1b2 feat: Some devices, such as DJI, send the command 'DataTransfer', but this command is useless (#336)
Co-authored-by: yjx <yjx>
2025-09-16 14:24:25 +08:00
langhuihui
825328118a fix: BasicAuth for grpc-gateway 2025-09-16 14:03:22 +08:00
18 changed files with 42 additions and 39 deletions

4
.gitignore vendored
View File

@@ -13,13 +13,15 @@ bin
*.flv
pullcf.yaml
*.zip
*.mp4
!plugin/hls/hls.js.zip
__debug*
.cursorrules
example/default/*
!example/default/main.go
!example/default/config.yaml
!example/default/test.flv
!example/default/test.mp4
shutdown.sh
!example/test/test.db
*.mp4
shutdown.bat

View File

@@ -10,6 +10,8 @@ COPY monibuca_amd64 ./monibuca_amd64
COPY monibuca_arm64 ./monibuca_arm64
COPY admin.zip ./admin.zip
COPY example/default/test.mp4 ./test.mp4
COPY example/default/test.flv ./test.flv
# Install tcpdump
RUN apt-get update && apt-get install -y tcpdump && rm -rf /var/lib/apt/lists/*

View File

@@ -117,6 +117,7 @@ The following build tags can be used to customize your build:
| duckdb | Enables the duckdb DB |
| taskpanic | Throws panic, for testing |
| fasthttp | Enables the fasthttp server instead of net/http |
| enable_buddy | Enables the buddy memory pre-allocation |
<p align="right">(<a href="#readme-top">back to top</a>)</p>
@@ -166,7 +167,7 @@ Contributions are what make the open source community such an amazing place to l
## License
Distributed under the MIT License. See `LICENSE` for more information.
Distributed under the AGPL License. See `LICENSE` for more information.
<p align="right">(<a href="#readme-top">back to top</a>)</p>

View File

@@ -116,6 +116,7 @@ go run -tags sqlite main.go
| duckdb | 启用 DuckDB 存储 |
| taskpanic | 抛出 panic用于测试 |
| fasthttp | 使用 fasthttp 服务器代替标准库 |
| enable_buddy | 开启 buddy 内存预申请|
<p align="right">(<a href="#readme-top">返回顶部</a>)</p>

View File

@@ -1,7 +1,7 @@
global:
location:
"^/hdl/(.*)": "/flv/$1" # 兼容 v4
"^/stress/(.*)": "/test/$1" # 5.0.x
"^/stress/api/(.*)": "/test/api/stress/$1" # 5.0.x
"^/monitor/(.*)": "/debug/$1" # 5.0.x
loglevel: debug
admin:

View File

@@ -16,6 +16,7 @@ import (
_ "m7s.live/v5/plugin/onvif"
_ "m7s.live/v5/plugin/preview"
_ "m7s.live/v5/plugin/rtmp"
_ "m7s.live/v5/plugin/rtp"
_ "m7s.live/v5/plugin/rtsp"
_ "m7s.live/v5/plugin/sei"
_ "m7s.live/v5/plugin/snap"

BIN
example/default/test.flv Normal file

Binary file not shown.

BIN
example/default/test.mp4 Normal file

Binary file not shown.

View File

@@ -1,6 +1,7 @@
package config
import (
"log/slog"
"net/http"
"m7s.live/v5/pkg/util"
@@ -10,8 +11,6 @@ import (
"time"
)
var _ HTTPConfig = (*HTTP)(nil)
type Middleware func(string, http.Handler) http.Handler
type HTTP struct {
ListenAddr string `desc:"监听地址"`
@@ -28,16 +27,27 @@ type HTTP struct {
grpcMux *runtime.ServeMux
middlewares []Middleware
}
type HTTPConfig interface {
GetHTTPConfig() *HTTP
// Handle(string, http.Handler)
// Handler(*http.Request) (http.Handler, string)
// AddMiddleware(Middleware)
func (config *HTTP) logHandler(logger *slog.Logger, handler http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
logger.Debug("visit", "path", r.URL.String(), "remote", r.RemoteAddr)
handler.ServeHTTP(rw, r)
})
}
func (config *HTTP) GetHandler() http.Handler {
func (config *HTTP) GetHandler(logger *slog.Logger) (h http.Handler) {
if config.grpcMux != nil {
return config.grpcMux
h = config.grpcMux
if logger != nil {
h = config.logHandler(logger, h)
}
if config.CORS {
h = util.CORS(h)
}
if config.UserName != "" && config.Password != "" {
h = util.BasicAuth(config.UserName, config.Password, h)
}
return
}
return config.mux
}
@@ -79,11 +89,3 @@ func (config *HTTP) Handle(path string, f http.Handler, last bool) {
}
config.mux.Handle(path, f)
}
func (config *HTTP) GetHTTPConfig() *HTTP {
return config
}
// func (config *HTTP) Handler(r *http.Request) (h http.Handler, pattern string) {
// return config.mux.Handler(r)
// }

View File

@@ -35,7 +35,7 @@ func (task *ListenHTTPWork) Start() (err error) {
ReadTimeout: task.HTTP.ReadTimeout,
WriteTimeout: task.HTTP.WriteTimeout,
IdleTimeout: task.HTTP.IdleTimeout,
Handler: task.GetHandler(),
Handler: task.GetHandler(task.Logger),
}
return
}
@@ -61,7 +61,7 @@ func (task *ListenHTTPSWork) Start() (err error) {
ReadTimeout: task.HTTP.ReadTimeout,
WriteTimeout: task.HTTP.WriteTimeout,
IdleTimeout: task.HTTP.IdleTimeout,
Handler: task.HTTP.GetHandler(),
Handler: task.HTTP.GetHandler(task.Logger),
TLSConfig: &tls.Config{
Certificates: []tls.Certificate{cer},
CipherSuites: []uint16{

View File

@@ -220,6 +220,7 @@ func CORS(next http.Handler) http.Handler {
header.Set("Access-Control-Allow-Credentials", "true")
header.Set("Cross-Origin-Resource-Policy", "cross-origin")
header.Set("Access-Control-Allow-Headers", "Content-Type,Access-Token,Authorization")
header.Set("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
header.Set("Access-Control-Allow-Private-Network", "true")
origin := r.Header["Origin"]
if len(origin) == 0 {

View File

@@ -72,7 +72,7 @@ func (task *CascadeClient) Run() (err error) {
if s, err = task.AcceptStream(task.Task.Context); err == nil {
task.AddTask(&cascade.ReceiveRequestTask{
Stream: s,
Handler: task.cfg.GetGlobalCommonConf().GetHandler(),
Handler: task.cfg.GetGlobalCommonConf().GetHandler(task.Logger),
Connection: task.Connection,
Plugin: &task.cfg.Plugin,
})

View File

@@ -125,7 +125,7 @@ func (task *CascadeServer) Go() (err error) {
var receiveRequestTask cascade.ReceiveRequestTask
receiveRequestTask.Connection = task.Connection
receiveRequestTask.Plugin = &task.conf.Plugin
receiveRequestTask.Handler = task.conf.GetGlobalCommonConf().GetHandler()
receiveRequestTask.Handler = task.conf.GetGlobalCommonConf().GetHandler(task.Logger)
if receiveRequestTask.Stream, err = task.AcceptStream(task); err == nil {
task.AddTask(&receiveRequestTask)
}

View File

@@ -427,6 +427,8 @@ func (d *Device) onMessage(req *sip.Request, tx sip.ServerTransaction, msg *gb28
d.Info("Broadcast message", "body", req.Body())
case "DeviceControl":
d.Info("DeviceControl message", "body", req.Body())
case "DataTransfer":
/*todo*/
default:
d.Warn("Not supported CmdType", "CmdType", msg.CmdType, "body", req.Body())
err = tx.Respond(sip.NewResponseFromRequest(req, http.StatusBadRequest, "", nil))

View File

@@ -29,7 +29,7 @@ func (r *RTPUDPReader) Read(packet *rtp.Packet) error {
if ordered != nil {
break
}
var buf [MTUSize]byte
var buf [ReceiveMTU]byte
var pack rtp.Packet
n, err := r.Reader.Read(buf[:])
if err != nil {

View File

@@ -59,6 +59,7 @@ const (
startBit = 1 << 7
endBit = 1 << 6
MTUSize = 1460
ReceiveMTU = 1500
)
func (r *VideoFrame) Recycle() {

View File

@@ -137,7 +137,7 @@ func (IO *MultipleConnection) Receive() {
}
packet := frame.Packets.GetNextPointer()
for {
buf := mem.Malloc(mrtp.MTUSize)
buf := mem.Malloc(mrtp.ReceiveMTU)
if n, _, err = track.Read(buf); err == nil {
mem.FreeRest(&buf, n)
err = packet.Unmarshal(buf)
@@ -200,7 +200,7 @@ func (IO *MultipleConnection) Receive() {
lastPLISent = time.Now()
}
buf := mem.Malloc(mrtp.MTUSize)
buf := mem.Malloc(mrtp.ReceiveMTU)
if n, _, err = track.Read(buf); err == nil {
mem.FreeRest(&buf, n)
err = packet.Unmarshal(buf)
@@ -212,6 +212,7 @@ func (IO *MultipleConnection) Receive() {
mem.Free(buf)
continue
}
if packet.Timestamp == writer.VideoFrame.Packets[0].Timestamp {
writer.VideoFrame.AddRecycleBytes(buf)
packet = writer.VideoFrame.Packets.GetNextPointer()

View File

@@ -17,7 +17,6 @@ import (
"gopkg.in/yaml.v3"
"github.com/shirou/gopsutil/v4/cpu"
"google.golang.org/protobuf/proto"
"m7s.live/v5/pkg/config"
"m7s.live/v5/pkg/task"
@@ -234,16 +233,6 @@ func (s *Server) Start() (err error) {
var httpMux http.Handler = httpConf.CreateHttpMux()
mux := runtime.NewServeMux(
runtime.WithMarshalerOption("text/plain", &pb.TextPlain{}),
runtime.WithForwardResponseOption(func(ctx context.Context, w http.ResponseWriter, m proto.Message) error {
header := w.Header()
header.Set("Access-Control-Allow-Credentials", "true")
header.Set("Cross-Origin-Resource-Policy", "cross-origin")
header.Set("Access-Control-Allow-Headers", "Content-Type,Access-Token,Authorization")
header.Set("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
header.Set("Access-Control-Allow-Private-Network", "true")
header.Set("Access-Control-Allow-Origin", "*")
return nil
}),
runtime.WithRoutingErrorHandler(func(_ context.Context, _ *runtime.ServeMux, _ runtime.Marshaler, w http.ResponseWriter, r *http.Request, _ int) {
httpMux.ServeHTTP(w, r)
}),
@@ -658,7 +647,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Rewrite the URL path and handle locally
r.URL.Path = pattern.ReplaceAllString(r.URL.Path, target)
// Forward to local handler
s.config.HTTP.GetHandler().ServeHTTP(w, r)
s.config.HTTP.GetHandler(s.Logger).ServeHTTP(w, r)
return
}
}