Browse Source

Add support for libcamera Autofocus parameters (#1417)

* [DEV #1416] Add support for libcamera Autofocus parameters

* [DEVMINOR] Fix Go formatting

* [DEV] Support AF window parameter for rpiCamera

* [DEV] Update default .yml file to add rpiCameraAfWindow parameter
pull/970/head
Azsde 4 years ago committed by GitHub
parent
commit
4841189456
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      internal/conf/path.go
  2. 5
      internal/core/source_static.go
  3. 6
      internal/rpicamera/exe/Makefile
  4. 65
      internal/rpicamera/exe/camera.cpp
  5. 17
      internal/rpicamera/exe/parameters.c
  6. 9
      internal/rpicamera/exe/parameters.h
  7. 6
      internal/rpicamera/exe/window.c
  8. 8
      internal/rpicamera/exe/window.h
  9. 5
      internal/rpicamera/params.go
  10. 5
      internal/rpicamera/rpicamera.go
  11. 18
      rtsp-simple-server.yml

5
internal/conf/path.go

@ -73,6 +73,11 @@ type PathConf struct {
RPICameraBitrate int `json:"rpiCameraBitrate"` RPICameraBitrate int `json:"rpiCameraBitrate"`
RPICameraProfile string `json:"rpiCameraProfile"` RPICameraProfile string `json:"rpiCameraProfile"`
RPICameraLevel string `json:"rpiCameraLevel"` RPICameraLevel string `json:"rpiCameraLevel"`
RPICameraAfMode string `json:"rpiCameraAfMode"`
RPICameraAfRange string `json:"rpiCameraAfRange"`
RPICameraAfSpeed string `json:"rpiCameraAfSpeed"`
RPICameraLensPosition float64 `json:"rpiCameraLensPosition"`
RPICameraAfWindow string `json:"rpiCameraAfWindow"`
// authentication // authentication
PublishUser Credential `json:"publishUser"` PublishUser Credential `json:"publishUser"`

5
internal/core/source_static.go

@ -110,6 +110,11 @@ func newSourceStatic(
Bitrate: conf.RPICameraBitrate, Bitrate: conf.RPICameraBitrate,
Profile: conf.RPICameraProfile, Profile: conf.RPICameraProfile,
Level: conf.RPICameraLevel, Level: conf.RPICameraLevel,
AfMode: conf.RPICameraAfMode,
AfRange: conf.RPICameraAfRange,
AfSpeed: conf.RPICameraAfSpeed,
LensPosition: conf.RPICameraLensPosition,
AfWindow: conf.RPICameraAfWindow,
}, },
s) s)
} }

6
internal/rpicamera/exe/Makefile

@ -3,7 +3,8 @@ CFLAGS = \
-Werror \ -Werror \
-Wall \ -Wall \
-Wextra \ -Wextra \
-Wno-unused-parameter -Wno-unused-parameter \
-Wno-unused-result
CXXFLAGS = \ CXXFLAGS = \
-Ofast \ -Ofast \
@ -11,6 +12,7 @@ CXXFLAGS = \
-Wall \ -Wall \
-Wextra \ -Wextra \
-Wno-unused-parameter \ -Wno-unused-parameter \
-Wno-unused-result \
-std=c++17 \ -std=c++17 \
$$(pkg-config --cflags libcamera) $$(pkg-config --cflags libcamera)
@ -24,7 +26,7 @@ OBJS = \
encoder.o \ encoder.o \
main.o \ main.o \
parameters.o \ parameters.o \
roi.o \ window.o \
sensor_mode.o sensor_mode.o
all: exe all: exe

65
internal/rpicamera/exe/camera.cpp

@ -334,6 +334,71 @@ bool camera_start(camera_t *cam) {
int64_t frame_time = 1000000 / camp->params->fps; int64_t frame_time = 1000000 / camp->params->fps;
ctrls.set(controls::FrameDurationLimits, Span<const int64_t, 2>({ frame_time, frame_time })); ctrls.set(controls::FrameDurationLimits, Span<const int64_t, 2>({ frame_time, frame_time }));
int af_mode;
if (strcmp(camp->params->af_mode, "manual") == 0) {
af_mode = controls::AfModeManual;
} else if (strcmp(camp->params->af_mode, "auto") == 0) {
af_mode = controls::AfModeAuto;
} else if (strcmp(camp->params->af_mode, "continuous") == 0) {
af_mode = controls::AfModeContinuous;
} else {
af_mode = controls::AfModeManual;
}
ctrls.set(controls::AfMode, af_mode);
int af_range;
if (strcmp(camp->params->af_range, "normal") == 0) {
af_range = controls::AfRangeNormal;
} else if (strcmp(camp->params->af_range, "macro") == 0) {
af_range = controls::AfRangeMacro;
} else if (strcmp(camp->params->af_range, "full") == 0) {
af_range = controls::AfRangeFull;
} else {
af_range = controls::AfRangeNormal;
}
ctrls.set(controls::AfRange, af_range);
int af_speed;
if (strcmp(camp->params->af_range, "normal") == 0) {
af_speed = controls::AfSpeedNormal;
} else if (strcmp(camp->params->af_range, "fast") == 0) {
af_speed = controls::AfSpeedFast;
} else {
af_speed = controls::AfSpeedNormal;
}
ctrls.set(controls::AfSpeed, af_speed);
// Lens Position
ctrls.set(controls::LensPosition, camp->params->lens_position);
// Af Window
if (camp->params->af_window != NULL) {
std::optional<Rectangle> opt = camp->camera->properties().get(properties::ScalerCropMaximum);
Rectangle sensor_area;
try {
sensor_area = opt.value();
} catch(const std::bad_optional_access& exc) {
set_error("get(ScalerCropMaximum) failed");
return false;
}
Rectangle afwindows_rectangle[1];
afwindows_rectangle[0] = Rectangle (
camp->params->af_window->x * sensor_area.width,
camp->params->af_window->y * sensor_area.height,
camp->params->af_window->width * sensor_area.width,
camp->params->af_window->height * sensor_area.height);
afwindows_rectangle[0].translateBy(sensor_area.topLeft());
//activate the AfMeteringWindows
ctrls.set(controls::AfMetering, controls::AfMeteringWindows);
//set window
ctrls.set(controls::AfWindows, afwindows_rectangle);
}
int res = camp->camera->start(&ctrls); int res = camp->camera->start(&ctrls);
if (res != 0) { if (res != 0) {
set_error("Camera.start() failed"); set_error("Camera.start() failed");

17
internal/rpicamera/exe/parameters.c

@ -39,7 +39,7 @@ bool parameters_load(parameters_t *params) {
params->ev = atof(getenv("EV")); params->ev = atof(getenv("EV"));
if (strlen(getenv("ROI")) != 0) { if (strlen(getenv("ROI")) != 0) {
bool ok = roi_load(getenv("ROI"), &params->roi); bool ok = window_load(getenv("ROI"), &params->roi);
if (!ok) { if (!ok) {
set_error("invalid ROI"); set_error("invalid ROI");
return false; return false;
@ -85,5 +85,20 @@ bool parameters_load(parameters_t *params) {
params->buffer_count = 6; params->buffer_count = 6;
params->capture_buffer_count = params->buffer_count * 2; params->capture_buffer_count = params->buffer_count * 2;
params->af_mode = getenv("AF_MODE");
params->af_range = getenv("AF_RANGE");
params->af_speed = getenv("AF_SPEED");
params->lens_position = atof(getenv("LENS_POSITION"));
if (strlen(getenv("AF_WINDOW")) != 0) {
bool ok = window_load(getenv("AF_WINDOW"), &params->af_window);
if (!ok) {
set_error("invalid AF_WINDOW");
return false;
}
} else {
params->af_window = NULL;
}
return true; return true;
} }

9
internal/rpicamera/exe/parameters.h

@ -3,7 +3,7 @@
#include <stdbool.h> #include <stdbool.h>
#include "roi.h" #include "window.h"
#include "sensor_mode.h" #include "sensor_mode.h"
typedef struct { typedef struct {
@ -23,7 +23,7 @@ typedef struct {
const char *metering; const char *metering;
float gain; float gain;
float ev; float ev;
roi_t *roi; window_t *roi;
const char *tuning_file; const char *tuning_file;
sensor_mode_t *mode; sensor_mode_t *mode;
unsigned int fps; unsigned int fps;
@ -31,6 +31,11 @@ typedef struct {
unsigned int bitrate; unsigned int bitrate;
unsigned int profile; unsigned int profile;
unsigned int level; unsigned int level;
const char *af_mode;
const char *af_range;
const char *af_speed;
float lens_position;
window_t *af_window;
// private // private
unsigned int buffer_count; unsigned int buffer_count;

6
internal/rpicamera/exe/roi.c → internal/rpicamera/exe/window.c

@ -1,9 +1,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "roi.h" #include "window.h"
bool roi_load(const char *encoded, roi_t **mode) { bool window_load(const char *encoded, window_t **mode) {
float vals[4]; float vals[4];
int i = 0; int i = 0;
char *token = strtok((char *)encoded, ","); char *token = strtok((char *)encoded, ",");
@ -21,7 +21,7 @@ bool roi_load(const char *encoded, roi_t **mode) {
return false; return false;
} }
*mode = malloc(sizeof(roi_t)); *mode = malloc(sizeof(window_t));
(*mode)->x = vals[0]; (*mode)->x = vals[0];
(*mode)->y = vals[1]; (*mode)->y = vals[1];
(*mode)->width = vals[2]; (*mode)->width = vals[2];

8
internal/rpicamera/exe/roi.h → internal/rpicamera/exe/window.h

@ -1,5 +1,5 @@
#ifndef __ROI_H__ #ifndef __WINDOW_H__
#define __ROI_H__ #define __WINDOW_H__
#include <stdbool.h> #include <stdbool.h>
@ -8,8 +8,8 @@ typedef struct {
float y; float y;
float width; float width;
float height; float height;
} roi_t; } window_t;
bool roi_load(const char *encoded, roi_t **mode); bool window_load(const char *encoded, window_t **mode);
#endif #endif

5
internal/rpicamera/params.go

@ -26,4 +26,9 @@ type Params struct {
Bitrate int Bitrate int
Profile string Profile string
Level string Level string
AfMode string
AfRange string
AfSpeed string
LensPosition float64
AfWindow string
} }

5
internal/rpicamera/rpicamera.go

@ -145,6 +145,11 @@ func New(
"BITRATE=" + strconv.FormatInt(int64(params.Bitrate), 10), "BITRATE=" + strconv.FormatInt(int64(params.Bitrate), 10),
"PROFILE=" + params.Profile, "PROFILE=" + params.Profile,
"LEVEL=" + params.Level, "LEVEL=" + params.Level,
"AF_MODE=" + params.AfMode,
"AF_RANGE=" + params.AfRange,
"AF_SPEED=" + params.AfSpeed,
"LENS_POSITION=" + strconv.FormatFloat(params.LensPosition, 'f', -1, 64),
"AF_WINDOW=" + params.AfWindow,
} }
exe, err := newEmbeddedExe(exeContent, env) exe, err := newEmbeddedExe(exeContent, env)

18
rtsp-simple-server.yml

@ -327,6 +327,24 @@ paths:
rpiCameraProfile: main rpiCameraProfile: main
# H264 level # H264 level
rpiCameraLevel: '4.1' rpiCameraLevel: '4.1'
# Autofocus mode
# values: manual, auto, continuous
rpiCameraAfMode: continuous
# Autofocus range
# values: normal, macro, full
rpiCameraAfRange: normal
# Autofocus speed
# values: normal, fast
rpiCameraAfSpeed: normal
# Lens position (for manual autofocus only), will be set to focus to a specific distance
# calculated by the following formula: d = 1 / value
# Examples: 0 moves the lens to infinity.
# 0.5 moves the lens to focus on objects 2m away.
# 2 moves the lens to focus on objects 50cm away.
rpiCameraLensPosition: 0.0
# Specifies the autofocus window, in the form x,y,width,height where the coordinates
# are given as a proportion of the entire image.
rpiCameraAfWindow:
# Username required to publish. # Username required to publish.
# SHA256-hashed values can be inserted with the "sha256:" prefix. # SHA256-hashed values can be inserted with the "sha256:" prefix.

Loading…
Cancel
Save