Browse Source

rpi camera: add rpiCameraHDR parameter (#1876) (#2083)

pull/2086/head
Alessandro Ros 2 years ago committed by GitHub
parent
commit
6d342082c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      apidocs/openapi.yaml
  2. 1
      internal/conf/path.go
  3. 1
      internal/core/rpicamera_source.go
  4. 22
      internal/rpicamera/exe/camera.cpp
  5. 2
      internal/rpicamera/exe/parameters.c
  6. 1
      internal/rpicamera/exe/parameters.h
  7. 45
      internal/rpicamera/params.go
  8. 43
      internal/rpicamera/rpicamera.go
  9. 2
      mediamtx.yml

2
apidocs/openapi.yaml

@ -264,6 +264,8 @@ components:
type: number type: number
rpiCameraROI: rpiCameraROI:
type: string type: string
rpiCameraHDR:
type: boolean
rpiCameraTuningFile: rpiCameraTuningFile:
type: string type: string
rpiCameraMode: rpiCameraMode:

1
internal/conf/path.go

@ -90,6 +90,7 @@ type PathConf struct {
RPICameraGain float64 `json:"rpiCameraGain"` RPICameraGain float64 `json:"rpiCameraGain"`
RPICameraEV float64 `json:"rpiCameraEV"` RPICameraEV float64 `json:"rpiCameraEV"`
RPICameraROI string `json:"rpiCameraROI"` RPICameraROI string `json:"rpiCameraROI"`
RPICameraHDR bool `json:"rpiCameraHDR"`
RPICameraTuningFile string `json:"rpiCameraTuningFile"` RPICameraTuningFile string `json:"rpiCameraTuningFile"`
RPICameraMode string `json:"rpiCameraMode"` RPICameraMode string `json:"rpiCameraMode"`
RPICameraFPS float64 `json:"rpiCameraFPS"` RPICameraFPS float64 `json:"rpiCameraFPS"`

1
internal/core/rpicamera_source.go

@ -32,6 +32,7 @@ func paramsFromConf(cnf *conf.PathConf) rpicamera.Params {
Gain: cnf.RPICameraGain, Gain: cnf.RPICameraGain,
EV: cnf.RPICameraEV, EV: cnf.RPICameraEV,
ROI: cnf.RPICameraROI, ROI: cnf.RPICameraROI,
HDR: cnf.RPICameraHDR,
TuningFile: cnf.RPICameraTuningFile, TuningFile: cnf.RPICameraTuningFile,
Mode: cnf.RPICameraMode, Mode: cnf.RPICameraMode,
FPS: cnf.RPICameraFPS, FPS: cnf.RPICameraFPS,

22
internal/rpicamera/exe/camera.cpp

@ -4,6 +4,9 @@
#include <sys/mman.h> #include <sys/mman.h>
#include <iostream> #include <iostream>
#include <mutex> #include <mutex>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <libcamera/camera_manager.h> #include <libcamera/camera_manager.h>
#include <libcamera/camera.h> #include <libcamera/camera.h>
@ -105,7 +108,26 @@ static uint8_t *map_buffer(FrameBuffer *buffer) {
return NULL; return NULL;
} }
// https://github.com/raspberrypi/libcamera-apps/blob/a6267d51949d0602eedf60f3ddf8c6685f652812/core/options.cpp#L101
static void set_hdr(bool hdr) {
bool ok = false;
for (int i = 0; i < 4 && !ok; i++)
{
std::string dev("/dev/v4l-subdev");
dev += (char)('0' + i);
int fd = open(dev.c_str(), O_RDWR, 0);
if (fd < 0)
continue;
v4l2_control ctrl { V4L2_CID_WIDE_DYNAMIC_RANGE, hdr };
ok = !ioctl(fd, VIDIOC_S_CTRL, &ctrl);
close(fd);
}
}
bool camera_create(const parameters_t *params, camera_frame_cb frame_cb, camera_t **cam) { bool camera_create(const parameters_t *params, camera_frame_cb frame_cb, camera_t **cam) {
set_hdr(params->hdr);
// We make sure to set the environment variable before libcamera init // We make sure to set the environment variable before libcamera init
setenv("LIBCAMERA_RPI_TUNING_FILE", params->tuning_file, 1); setenv("LIBCAMERA_RPI_TUNING_FILE", params->tuning_file, 1);

2
internal/rpicamera/exe/parameters.c

@ -81,6 +81,8 @@ bool parameters_unserialize(parameters_t *params, const uint8_t *buf, size_t buf
} }
} }
free(decoded_val); free(decoded_val);
} else if (strcmp(key, "HDR") == 0) {
params->hdr = (strcmp(val, "1") == 0);
} else if (strcmp(key, "TuningFile") == 0) { } else if (strcmp(key, "TuningFile") == 0) {
params->tuning_file = base64_decode(val); params->tuning_file = base64_decode(val);
} else if (strcmp(key, "Mode") == 0) { } else if (strcmp(key, "Mode") == 0) {

1
internal/rpicamera/exe/parameters.h

@ -25,6 +25,7 @@ typedef struct {
float gain; float gain;
float ev; float ev;
window_t *roi; window_t *roi;
bool hdr;
char *tuning_file; char *tuning_file;
sensor_mode_t *mode; sensor_mode_t *mode;
float fps; float fps;

45
internal/rpicamera/params.go

@ -1,5 +1,12 @@
package rpicamera package rpicamera
import (
"encoding/base64"
"reflect"
"strconv"
"strings"
)
// Params is a set of camera parameters. // Params is a set of camera parameters.
type Params struct { type Params struct {
CameraID int CameraID int
@ -19,6 +26,7 @@ type Params struct {
Gain float64 Gain float64
EV float64 EV float64
ROI string ROI string
HDR bool
TuningFile string TuningFile string
Mode string Mode string
FPS float64 FPS float64
@ -34,3 +42,40 @@ type Params struct {
TextOverlayEnable bool TextOverlayEnable bool
TextOverlay string TextOverlay string
} }
func (p Params) serialize() []byte { //nolint:unused
rv := reflect.ValueOf(p)
rt := rv.Type()
nf := rv.NumField()
ret := make([]string, nf)
for i := 0; i < nf; i++ {
entry := rt.Field(i).Name + ":"
f := rv.Field(i)
switch f.Kind() {
case reflect.Int:
entry += strconv.FormatInt(f.Int(), 10)
case reflect.Float64:
entry += strconv.FormatFloat(f.Float(), 'f', -1, 64)
case reflect.String:
entry += base64.StdEncoding.EncodeToString([]byte(f.String()))
case reflect.Bool:
if f.Bool() {
entry += "1"
} else {
entry += "0"
}
default:
panic("unhandled type")
}
ret[i] = entry
}
return []byte(strings.Join(ret, " "))
}

43
internal/rpicamera/rpicamera.go

@ -6,11 +6,9 @@ package rpicamera
import ( import (
"debug/elf" "debug/elf"
_ "embed" _ "embed"
"encoding/base64"
"fmt" "fmt"
"os" "os"
"os/exec" "os/exec"
"reflect"
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
@ -50,43 +48,6 @@ func startEmbeddedExe(content []byte, env []string) (*exec.Cmd, error) {
return cmd, nil return cmd, nil
} }
func serializeParams(p Params) []byte {
rv := reflect.ValueOf(p)
rt := rv.Type()
nf := rv.NumField()
ret := make([]string, nf)
for i := 0; i < nf; i++ {
entry := rt.Field(i).Name + ":"
f := rv.Field(i)
switch f.Kind() {
case reflect.Int:
entry += strconv.FormatInt(f.Int(), 10)
case reflect.Float64:
entry += strconv.FormatFloat(f.Float(), 'f', -1, 64)
case reflect.String:
entry += base64.StdEncoding.EncodeToString([]byte(f.String()))
case reflect.Bool:
if f.Bool() {
entry += "1"
} else {
entry += "0"
}
default:
panic("unhandled type")
}
ret[i] = entry
}
return []byte(strings.Join(ret, " "))
}
func findLibrary(name string) (string, error) { func findLibrary(name string) (string, error) {
byts, err := exec.Command("ldconfig", "-p").Output() byts, err := exec.Command("ldconfig", "-p").Output()
if err == nil { if err == nil {
@ -220,7 +181,7 @@ func New(
return nil, err return nil, err
} }
c.pipeConf.write(append([]byte{'c'}, serializeParams(params)...)) c.pipeConf.write(append([]byte{'c'}, params.serialize()...))
c.waitDone = make(chan error) c.waitDone = make(chan error)
go func() { go func() {
@ -266,7 +227,7 @@ func (c *RPICamera) Close() {
} }
func (c *RPICamera) ReloadParams(params Params) { func (c *RPICamera) ReloadParams(params Params) {
c.pipeConf.write(append([]byte{'c'}, serializeParams(params)...)) c.pipeConf.write(append([]byte{'c'}, params.serialize()...))
} }
func (c *RPICamera) readReady() error { func (c *RPICamera) readReady() error {

2
mediamtx.yml

@ -366,6 +366,8 @@ paths:
rpiCameraEV: 0 rpiCameraEV: 0
# Region of interest, in format x,y,width,height # Region of interest, in format x,y,width,height
rpiCameraROI: rpiCameraROI:
# whether to enable HDR on Raspberry Camera 3.
rpiCameraHDR: false
# tuning file # tuning file
rpiCameraTuningFile: rpiCameraTuningFile:
# sensor mode, in format [width]:[height]:[bit-depth]:[packing] # sensor mode, in format [width]:[height]:[bit-depth]:[packing]

Loading…
Cancel
Save