rpicamera: support libcamera 0.0.2

This commit is contained in:
aler9 2022-12-08 23:49:53 +01:00
parent 7fef5500cb
commit 3f5c550baf
6 changed files with 79 additions and 43 deletions

View File

@ -1,5 +1,5 @@
# do not add .git, since it is needed to extract the tag
/tmp
/binaries
/coverage*.txt
/apidocs/*.html

View File

@ -534,11 +534,11 @@ After starting the server, the webcam can be reached on `rtsp://localhost:8554/c
_rtsp-simple-server_ natively support the Raspberry Pi Camera, enabling high-quality and low-latency video streaming from the camera to any user. There are a couple of requisites:
1. The server must run on a Raspberry Pi, with Raspberry Pi OS bullseye or newer as operative system.
1. The server must run on a Raspberry Pi, with Raspberry Pi OS bullseye or newer as operative system. Both 32 bit and 64 bit operative systems are supported.
2. Make sure that the legacy camera stack is disabled. Type `sudo raspi-config`, then go to `Interfacing options`, `enable/disable legacy camera support`, choose `no`. Reboot the system.
3. Make sure that the `libcamera` version is at least `0.0.1`, otherwise upgrade it with `sudo apt upgrade`.
3. Make sure that the `libcamera0` package version is at least `0.0.2`, otherwise upgrade it with `sudo apt update && sudo apt upgrade`.
If you want to run the standard (non-dockerized) version of the server, just download the server executable and make sure to pick the `arm64` variant if you're using the 64-bit version of the operative system. Then edit `rtsp-simple-server.yml` and replace everything inside section `paths` with the following content:

View File

@ -4,10 +4,8 @@
package rpicamera
import (
"fmt"
"os"
"os/exec"
"runtime"
"strconv"
"time"
)
@ -16,48 +14,14 @@ const (
tempPathPrefix = "/dev/shm/rtspss-embeddedexe-"
)
func getKernelArch() (string, error) {
cmd := exec.Command("uname", "-m")
byts, err := cmd.Output()
if err != nil {
return "", err
}
return string(byts[:len(byts)-1]), nil
}
// 32-bit embedded executables can't run on 64-bit.
func checkArch() error {
if runtime.GOARCH != "arm" {
return nil
}
arch, err := getKernelArch()
if err != nil {
return err
}
if arch == "aarch64" {
return fmt.Errorf("OS is 64-bit, you need the arm64 server version")
}
return nil
}
type embeddedExe struct {
cmd *exec.Cmd
}
func newEmbeddedExe(content []byte, env []string) (*embeddedExe, error) {
err := checkArch()
if err != nil {
return nil, err
}
tempPath := tempPathPrefix + strconv.FormatInt(time.Now().UnixNano(), 10)
err = os.WriteFile(tempPath, content, 0o755)
err := os.WriteFile(tempPath, content, 0o755)
if err != nil {
return nil, err
}

View File

@ -36,4 +36,6 @@ all: exe
$(CXX) $(CXXFLAGS) -c $< -o $@
exe: $(OBJS)
$(CXX) -o $@ $^ $(LDFLAGS)
$(CXX) $^ $(LDFLAGS) -o $@
patchelf --replace-needed libcamera.so.0.0.2 libcamera.so.x.x.x $@
patchelf --replace-needed libcamera-base.so.0.0.2 libcamera-base.so.x.x.x $@

View File

@ -6,7 +6,11 @@ package rpicamera
import (
_ "embed"
"fmt"
"os"
"os/exec"
"runtime"
"strconv"
"strings"
"time"
"github.com/aler9/gortsplib/pkg/h264"
@ -22,6 +26,61 @@ func bool2env(v bool) string {
return "0"
}
func getKernelArch() (string, error) {
cmd := exec.Command("uname", "-m")
byts, err := cmd.Output()
if err != nil {
return "", err
}
return string(byts[:len(byts)-1]), nil
}
// 32-bit embedded executables can't run on 64-bit.
func checkArch() error {
if runtime.GOARCH != "arm" {
return nil
}
arch, err := getKernelArch()
if err != nil {
return err
}
if arch == "aarch64" {
return fmt.Errorf("OS is 64-bit, you need the arm64 server version")
}
return nil
}
func setupSymlink(name string) error {
cmd := exec.Command("sh", "-c", "ldconfig -p | grep "+name+".so | awk '{ print $4 }'")
byts, err := cmd.Output()
if err != nil {
return err
}
lib := strings.TrimSpace(string(byts))
if lib == "" {
return fmt.Errorf(name + " not found")
}
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")
}
type RPICamera struct {
onData func(time.Duration, [][]byte)
@ -36,12 +95,23 @@ func New(
params Params,
onData func(time.Duration, [][]byte),
) (*RPICamera, error) {
err := checkArch()
if err != nil {
return nil, err
}
err = setupSymlinks()
if err != nil {
return nil, err
}
pipe, err := newPipe()
if err != nil {
return nil, err
}
env := []string{
"LD_LIBRARY_PATH=/dev/shm",
"PIPE_FD=" + strconv.FormatInt(int64(pipe.writeFD), 10),
"CAMERA_ID=" + strconv.FormatInt(int64(params.CameraID), 10),
"WIDTH=" + strconv.FormatInt(int64(params.Width), 10),

View File

@ -1,14 +1,14 @@
define DOCKERFILE_BINARIES
FROM $(RPI32_IMAGE) AS rpicamera32
RUN ["cross-build-start"]
RUN apt update && apt install -y --no-install-recommends g++ pkg-config make libcamera-dev
RUN apt update && apt install -y --no-install-recommends g++ pkg-config make libcamera-dev patchelf
WORKDIR /s/internal/rpicamera
COPY internal/rpicamera .
RUN cd exe && make -j$$(nproc)
FROM $(RPI64_IMAGE) AS rpicamera64
RUN ["cross-build-start"]
RUN apt update && apt install -y --no-install-recommends g++ pkg-config make libcamera-dev
RUN apt update && apt install -y --no-install-recommends g++ pkg-config make libcamera-dev patchelf
WORKDIR /s/internal/rpicamera
COPY internal/rpicamera .
RUN cd exe && make -j$$(nproc)