From 32d6cb4435c3970ca2b0b0345f14be0dc0db5122 Mon Sep 17 00:00:00 2001 From: Alessandro Ros Date: Mon, 20 Mar 2023 00:22:44 +0100 Subject: [PATCH] rpicamera: support two CSI cameras at once (#1573) (#1574) --- internal/conf/conf_test.go | 2 +- internal/conf/path.go | 6 ++- internal/core/core.go | 5 +++ internal/rpicamera/libcamera.go | 47 ++++++++++++++++++++++++ internal/rpicamera/libcamera_disabled.go | 12 ++++++ internal/rpicamera/rpicamera.go | 45 ----------------------- 6 files changed, 69 insertions(+), 48 deletions(-) create mode 100644 internal/rpicamera/libcamera.go create mode 100644 internal/rpicamera/libcamera_disabled.go diff --git a/internal/conf/conf_test.go b/internal/conf/conf_test.go index 52326322..3b4d4174 100644 --- a/internal/conf/conf_test.go +++ b/internal/conf/conf_test.go @@ -202,7 +202,7 @@ func TestConfErrors(t *testing.T) { " source: rpiCamera\n" + " cam2:\n" + " source: rpiCamera\n", - "'rpiCamera' is used as source in two paths ('cam1' and 'cam2')", + "'rpiCamera' with same camera ID 0 is used as source in two paths, 'cam1' and 'cam2'", }, } { t.Run(ca.name, func(t *testing.T) { diff --git a/internal/conf/path.go b/internal/conf/path.go index f3ea3b54..f002173f 100644 --- a/internal/conf/path.go +++ b/internal/conf/path.go @@ -195,8 +195,10 @@ func (pconf *PathConf) checkAndFillMissing(conf *Conf, name string) error { } for otherName, otherPath := range conf.Paths { - if otherPath != pconf && otherPath != nil && otherPath.Source == "rpiCamera" { - return fmt.Errorf("'rpiCamera' is used as source in two paths ('%s' and '%s')", name, otherName) + if otherPath != pconf && otherPath != nil && + otherPath.Source == "rpiCamera" && otherPath.RPICameraCamID == pconf.RPICameraCamID { + return fmt.Errorf("'rpiCamera' with same camera ID %d is used as source in two paths, '%s' and '%s'", + pconf.RPICameraCamID, name, otherName) } } diff --git a/internal/core/core.go b/internal/core/core.go index 9aec6cb3..41d66dbe 100644 --- a/internal/core/core.go +++ b/internal/core/core.go @@ -17,6 +17,7 @@ import ( "github.com/aler9/rtsp-simple-server/internal/externalcmd" "github.com/aler9/rtsp-simple-server/internal/logger" "github.com/aler9/rtsp-simple-server/internal/rlimit" + "github.com/aler9/rtsp-simple-server/internal/rpicamera" ) var version = "v0.0.0" @@ -84,6 +85,8 @@ func New(args []string) (*Core, bool) { // do not check for errors rlimit.Raise() + rpicamera.LibcameraSetup() + gin.SetMode(gin.ReleaseMode) ctx, ctxCancel := context.WithCancel(context.Background()) @@ -186,6 +189,8 @@ outer: p.ctxCancel() p.closeResources(nil, false) + + rpicamera.LibcameraCleanup() } func (p *Core) createResources(initial bool) error { diff --git a/internal/rpicamera/libcamera.go b/internal/rpicamera/libcamera.go new file mode 100644 index 00000000..bec06e70 --- /dev/null +++ b/internal/rpicamera/libcamera.go @@ -0,0 +1,47 @@ +//go:build rpicamera +// +build rpicamera + +package rpicamera + +import ( + "fmt" + "os" + "os/exec" + "strings" +) + +func findLibrary(name string) (string, error) { + byts, err := exec.Command("ldconfig", "-p").Output() + if err == nil { + for _, line := range strings.Split(string(byts), "\n") { + f := strings.Split(line, " => ") + if len(f) == 2 && strings.Contains(f[1], name+".so") { + return f[1], nil + } + } + } + + return "", fmt.Errorf("library '%s' not found", name) +} + +func setupSymlink(name string) error { + lib, err := findLibrary(name) + if err != nil { + return err + } + + os.Remove("/dev/shm/" + name + ".so.x.x.x") + return os.Symlink(lib, "/dev/shm/"+name+".so.x.x.x") +} + +// LibcameraSetup creates libcamera simlinks that are version agnostic. +func LibcameraSetup() { + setupSymlink("libcamera") + setupSymlink("libcamera-base") +} + +// LibcameraCleanup removes files created by LibcameraSetup. +func LibcameraCleanup() { + os.Remove("/dev/shm/libcamera-base.so.x.x.x") + os.Remove("/dev/shm/libcamera.so.x.x.x") +} diff --git a/internal/rpicamera/libcamera_disabled.go b/internal/rpicamera/libcamera_disabled.go new file mode 100644 index 00000000..325d3851 --- /dev/null +++ b/internal/rpicamera/libcamera_disabled.go @@ -0,0 +1,12 @@ +//go:build !rpicamera +// +build !rpicamera + +package rpicamera + +// LibcameraSetup creates libcamera simlinks that are version agnostic. +func LibcameraSetup() { +} + +// LibcameraCleanup removes files created by LibcameraSetup. +func LibcameraCleanup() { +} diff --git a/internal/rpicamera/rpicamera.go b/internal/rpicamera/rpicamera.go index 01802caa..88f04e62 100644 --- a/internal/rpicamera/rpicamera.go +++ b/internal/rpicamera/rpicamera.go @@ -53,45 +53,6 @@ func checkArch() error { return nil } -func findLibrary(name string) (string, error) { - byts, err := exec.Command("ldconfig", "-p").Output() - if err == nil { - for _, line := range strings.Split(string(byts), "\n") { - f := strings.Split(line, " => ") - if len(f) == 2 && strings.Contains(f[1], name+".so") { - return f[1], nil - } - } - } - - return "", fmt.Errorf("library '%s' not found", name) -} - -func setupSymlink(name string) error { - lib, err := findLibrary(name) - if err != nil { - return err - } - - os.Remove("/dev/shm/" + name + ".so.x.x.x") - return os.Symlink(lib, "/dev/shm/"+name+".so.x.x.x") -} - -// create libcamera simlinks that are version agnostic. -func setupSymlinks() error { - err := setupSymlink("libcamera") - if err != nil { - return err - } - - return setupSymlink("libcamera-base") -} - -func removeSymlinks() { - os.Remove("/dev/shm/libcamera-base.so.x.x.x") - os.Remove("/dev/shm/libcamera.so.x.x.x") -} - func startEmbeddedExe(content []byte, env []string) (*exec.Cmd, error) { tempPath := tempPathPrefix + strconv.FormatInt(time.Now().UnixNano(), 10) @@ -172,12 +133,6 @@ func New( return nil, err } - err = setupSymlinks() - if err != nil { - return nil, err - } - defer removeSymlinks() - c := &RPICamera{ onData: onData, }