Browse Source

add rpiCameraAWBGains (#2858) (#2954)

pull/2957/head
Alessandro Ros 2 years ago committed by GitHub
parent
commit
0f733bab26
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      apidocs/openapi.yaml
  2. 1
      internal/conf/conf_test.go
  3. 25
      internal/conf/env/env.go
  4. 3
      internal/conf/env/env_test.go
  5. 5
      internal/conf/path.go
  6. 1
      internal/core/path_manager.go
  7. 5
      internal/protocols/rpicamera/exe/camera.cpp
  8. 4
      internal/protocols/rpicamera/exe/parameters.c
  9. 2
      internal/protocols/rpicamera/exe/parameters.h
  10. 2
      internal/protocols/rpicamera/params.go
  11. 2
      internal/staticsources/rpicamera/source.go
  12. 3
      mediamtx.yml

6
apidocs/openapi.yaml

@ -298,6 +298,12 @@ components:
type: string type: string
rpiCameraAWB: rpiCameraAWB:
type: string type: string
rpiCameraAWBGains:
type: array
minItems: 2
maxItems: 2
items:
type: number
rpiCameraDenoise: rpiCameraDenoise:
type: string type: string
rpiCameraShutter: rpiCameraShutter:

1
internal/conf/conf_test.go

@ -66,6 +66,7 @@ func TestConfFromFile(t *testing.T) {
RPICameraSharpness: 1, RPICameraSharpness: 1,
RPICameraExposure: "normal", RPICameraExposure: "normal",
RPICameraAWB: "auto", RPICameraAWB: "auto",
RPICameraAWBGains: []float64{0, 0},
RPICameraDenoise: "off", RPICameraDenoise: "off",
RPICameraMetering: "centre", RPICameraMetering: "centre",
RPICameraFPS: 30, RPICameraFPS: 30,

25
internal/conf/env/env.go vendored

@ -188,6 +188,31 @@ func loadEnvInternal(env map[string]string, prefix string, prv reflect.Value) er
} }
return nil return nil
case rt.Elem() == reflect.TypeOf(float64(0)):
if ev, ok := env[prefix]; ok {
if ev == "" {
prv.Elem().Set(reflect.MakeSlice(prv.Elem().Type(), 0, 0))
} else {
if prv.IsNil() {
prv.Set(reflect.New(rt))
}
raw := strings.Split(ev, ",")
vals := make([]float64, len(raw))
for i, v := range raw {
tmp, err := strconv.ParseFloat(v, 64)
if err != nil {
return err
}
vals[i] = tmp
}
prv.Elem().Set(reflect.ValueOf(vals))
}
}
return nil
case rt.Elem().Kind() == reflect.Struct: case rt.Elem().Kind() == reflect.Struct:
if ev, ok := env[prefix]; ok && ev == "" { // special case: empty list if ev, ok := env[prefix]; ok && ev == "" { // special case: empty list
prv.Elem().Set(reflect.MakeSlice(prv.Elem().Type(), 0, 0)) prv.Elem().Set(reflect.MakeSlice(prv.Elem().Type(), 0, 0))

3
internal/conf/env/env_test.go vendored

@ -85,6 +85,7 @@ type testStruct struct {
MyDurationOpt *myDuration `json:"myDurationOpt"` MyDurationOpt *myDuration `json:"myDurationOpt"`
MyDurationOptUnset *myDuration `json:"myDurationOptUnset"` MyDurationOptUnset *myDuration `json:"myDurationOptUnset"`
MyMap map[string]*mapEntry `json:"myMap"` MyMap map[string]*mapEntry `json:"myMap"`
MySliceFloat []float64 `json:"mySliceFloat"`
MySliceString []string `json:"mySliceString"` MySliceString []string `json:"mySliceString"`
MySliceStringEmpty []string `json:"mySliceStringEmpty"` MySliceStringEmpty []string `json:"mySliceStringEmpty"`
MySliceStringOpt *[]string `json:"mySliceStringOpt"` MySliceStringOpt *[]string `json:"mySliceStringOpt"`
@ -113,6 +114,7 @@ func TestLoad(t *testing.T) {
"MYPREFIX_MYMAP_MYKEY": "", "MYPREFIX_MYMAP_MYKEY": "",
"MYPREFIX_MYMAP_MYKEY2_MYVALUE": "asd", "MYPREFIX_MYMAP_MYKEY2_MYVALUE": "asd",
"MYPREFIX_MYMAP_MYKEY2_MYSTRUCT_MYPARAM": "456", "MYPREFIX_MYMAP_MYKEY2_MYSTRUCT_MYPARAM": "456",
"MYPREFIX_MYSLICEFLOAT": "0.5,0.5",
"MYPREFIX_MYSLICESTRING": "val1,val2", "MYPREFIX_MYSLICESTRING": "val1,val2",
"MYPREFIX_MYSLICESTRINGEMPTY": "", "MYPREFIX_MYSLICESTRINGEMPTY": "",
"MYPREFIX_MYSLICESTRINGOPT": "aa", "MYPREFIX_MYSLICESTRINGOPT": "aa",
@ -160,6 +162,7 @@ func TestLoad(t *testing.T) {
}, },
}, },
}, },
MySliceFloat: []float64{0.5, 0.5},
MySliceString: []string{ MySliceString: []string{
"val1", "val1",
"val2", "val2",

5
internal/conf/path.go

@ -141,6 +141,7 @@ type Path struct {
RPICameraSharpness float64 `json:"rpiCameraSharpness"` RPICameraSharpness float64 `json:"rpiCameraSharpness"`
RPICameraExposure string `json:"rpiCameraExposure"` RPICameraExposure string `json:"rpiCameraExposure"`
RPICameraAWB string `json:"rpiCameraAWB"` RPICameraAWB string `json:"rpiCameraAWB"`
RPICameraAWBGains []float64 `json:"rpiCameraAWBGains"`
RPICameraDenoise string `json:"rpiCameraDenoise"` RPICameraDenoise string `json:"rpiCameraDenoise"`
RPICameraShutter int `json:"rpiCameraShutter"` RPICameraShutter int `json:"rpiCameraShutter"`
RPICameraMetering string `json:"rpiCameraMetering"` RPICameraMetering string `json:"rpiCameraMetering"`
@ -206,6 +207,7 @@ func (pconf *Path) setDefaults() {
pconf.RPICameraSharpness = 1 pconf.RPICameraSharpness = 1
pconf.RPICameraExposure = "normal" pconf.RPICameraExposure = "normal"
pconf.RPICameraAWB = "auto" pconf.RPICameraAWB = "auto"
pconf.RPICameraAWBGains = []float64{0, 0}
pconf.RPICameraDenoise = "off" pconf.RPICameraDenoise = "off"
pconf.RPICameraMetering = "centre" pconf.RPICameraMetering = "centre"
pconf.RPICameraFPS = 30 pconf.RPICameraFPS = 30
@ -467,6 +469,9 @@ func (pconf *Path) validate(conf *Conf, name string) error {
default: default:
return fmt.Errorf("invalid 'rpiCameraAWB' value") return fmt.Errorf("invalid 'rpiCameraAWB' value")
} }
if len(pconf.RPICameraAWBGains) != 2 {
return fmt.Errorf("invalid 'rpiCameraAWBGains' value")
}
switch pconf.RPICameraDenoise { switch pconf.RPICameraDenoise {
case "off", "cdn_off", "cdn_fast", "cdn_hq": case "off", "cdn_off", "cdn_fast", "cdn_hq":
default: default:

1
internal/core/path_manager.go

@ -23,6 +23,7 @@ func pathConfCanBeUpdated(oldPathConf *conf.Path, newPathConf *conf.Path) bool {
clone.RPICameraSharpness = newPathConf.RPICameraSharpness clone.RPICameraSharpness = newPathConf.RPICameraSharpness
clone.RPICameraExposure = newPathConf.RPICameraExposure clone.RPICameraExposure = newPathConf.RPICameraExposure
clone.RPICameraAWB = newPathConf.RPICameraAWB clone.RPICameraAWB = newPathConf.RPICameraAWB
clone.RPICameraAWBGains = newPathConf.RPICameraAWBGains
clone.RPICameraDenoise = newPathConf.RPICameraDenoise clone.RPICameraDenoise = newPathConf.RPICameraDenoise
clone.RPICameraShutter = newPathConf.RPICameraShutter clone.RPICameraShutter = newPathConf.RPICameraShutter
clone.RPICameraMetering = newPathConf.RPICameraMetering clone.RPICameraMetering = newPathConf.RPICameraMetering

5
internal/protocols/rpicamera/exe/camera.cpp

@ -346,6 +346,11 @@ static void fill_dynamic_controls(ControlList *ctrls, const parameters_t *params
} }
ctrls->set(controls::AwbMode, awb_mode); ctrls->set(controls::AwbMode, awb_mode);
if (params->awb_gain_red > 0 && params->awb_gain_blue > 0) {
ctrls->set(controls::ColourGains,
Span<const float, 2>({params->awb_gain_red, params->awb_gain_blue}));
}
int denoise_mode; int denoise_mode;
if (strcmp(params->denoise, "cdn_off") == 0) { if (strcmp(params->denoise, "cdn_off") == 0) {
denoise_mode = controls::draft::NoiseReductionModeMinimal; denoise_mode = controls::draft::NoiseReductionModeMinimal;

4
internal/protocols/rpicamera/exe/parameters.c

@ -61,6 +61,10 @@ bool parameters_unserialize(parameters_t *params, const uint8_t *buf, size_t buf
params->exposure = base64_decode(val); params->exposure = base64_decode(val);
} else if (strcmp(key, "AWB") == 0) { } else if (strcmp(key, "AWB") == 0) {
params->awb = base64_decode(val); params->awb = base64_decode(val);
} else if (strcmp(key, "AWBGainRed") == 0) {
params->awb_gain_red = atof(val);
} else if (strcmp(key, "AWBGainBlue") == 0) {
params->awb_gain_blue = atof(val);
} else if (strcmp(key, "Denoise") == 0) { } else if (strcmp(key, "Denoise") == 0) {
params->denoise = base64_decode(val); params->denoise = base64_decode(val);
} else if (strcmp(key, "Shutter") == 0) { } else if (strcmp(key, "Shutter") == 0) {

2
internal/protocols/rpicamera/exe/parameters.h

@ -20,6 +20,8 @@ typedef struct {
float sharpness; float sharpness;
char *exposure; char *exposure;
char *awb; char *awb;
float awb_gain_red;
float awb_gain_blue;
char *denoise; char *denoise;
unsigned int shutter; unsigned int shutter;
char *metering; char *metering;

2
internal/protocols/rpicamera/params.go

@ -21,6 +21,8 @@ type Params struct {
Sharpness float64 Sharpness float64
Exposure string Exposure string
AWB string AWB string
AWBGainRed float64
AWBGainBlue float64
Denoise string Denoise string
Shutter int Shutter int
Metering string Metering string

2
internal/staticsources/rpicamera/source.go

@ -39,6 +39,8 @@ func paramsFromConf(logLevel conf.LogLevel, cnf *conf.Path) rpicamera.Params {
Sharpness: cnf.RPICameraSharpness, Sharpness: cnf.RPICameraSharpness,
Exposure: cnf.RPICameraExposure, Exposure: cnf.RPICameraExposure,
AWB: cnf.RPICameraAWB, AWB: cnf.RPICameraAWB,
AWBGainRed: cnf.RPICameraAWBGains[0],
AWBGainBlue: cnf.RPICameraAWBGains[1],
Denoise: cnf.RPICameraDenoise, Denoise: cnf.RPICameraDenoise,
Shutter: cnf.RPICameraShutter, Shutter: cnf.RPICameraShutter,
Metering: cnf.RPICameraMetering, Metering: cnf.RPICameraMetering,

3
mediamtx.yml

@ -409,6 +409,9 @@ pathDefaults:
# auto-white-balance mode. # auto-white-balance mode.
# values: auto, incandescent, tungsten, fluorescent, indoor, daylight, cloudy, custom # values: auto, incandescent, tungsten, fluorescent, indoor, daylight, cloudy, custom
rpiCameraAWB: auto rpiCameraAWB: auto
# auto-white-balance fixed gains. This can be used in place of rpiCameraAWB.
# format: [red,blue]
rpiCameraAWBGains: [0, 0]
# denoise operating mode. # denoise operating mode.
# values: off, cdn_off, cdn_fast, cdn_hq # values: off, cdn_off, cdn_fast, cdn_hq
rpiCameraDenoise: "off" rpiCameraDenoise: "off"

Loading…
Cancel
Save