mirror of
https://github.com/bluenviron/mediamtx
synced 2025-01-20 22:21:01 +00:00
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
This commit is contained in:
parent
50a3d331d7
commit
4841189456
@ -73,6 +73,11 @@ type PathConf struct {
|
||||
RPICameraBitrate int `json:"rpiCameraBitrate"`
|
||||
RPICameraProfile string `json:"rpiCameraProfile"`
|
||||
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
|
||||
PublishUser Credential `json:"publishUser"`
|
||||
|
@ -86,30 +86,35 @@ func newSourceStatic(
|
||||
case conf.Source == "rpiCamera":
|
||||
s.impl = newRPICameraSource(
|
||||
rpicamera.Params{
|
||||
CameraID: conf.RPICameraCamID,
|
||||
Width: conf.RPICameraWidth,
|
||||
Height: conf.RPICameraHeight,
|
||||
HFlip: conf.RPICameraHFlip,
|
||||
VFlip: conf.RPICameraVFlip,
|
||||
Brightness: conf.RPICameraBrightness,
|
||||
Contrast: conf.RPICameraContrast,
|
||||
Saturation: conf.RPICameraSaturation,
|
||||
Sharpness: conf.RPICameraSharpness,
|
||||
Exposure: conf.RPICameraExposure,
|
||||
AWB: conf.RPICameraAWB,
|
||||
Denoise: conf.RPICameraDenoise,
|
||||
Shutter: conf.RPICameraShutter,
|
||||
Metering: conf.RPICameraMetering,
|
||||
Gain: conf.RPICameraGain,
|
||||
EV: conf.RPICameraEV,
|
||||
ROI: conf.RPICameraROI,
|
||||
TuningFile: conf.RPICameraTuningFile,
|
||||
Mode: conf.RPICameraMode,
|
||||
FPS: conf.RPICameraFPS,
|
||||
IDRPeriod: conf.RPICameraIDRPeriod,
|
||||
Bitrate: conf.RPICameraBitrate,
|
||||
Profile: conf.RPICameraProfile,
|
||||
Level: conf.RPICameraLevel,
|
||||
CameraID: conf.RPICameraCamID,
|
||||
Width: conf.RPICameraWidth,
|
||||
Height: conf.RPICameraHeight,
|
||||
HFlip: conf.RPICameraHFlip,
|
||||
VFlip: conf.RPICameraVFlip,
|
||||
Brightness: conf.RPICameraBrightness,
|
||||
Contrast: conf.RPICameraContrast,
|
||||
Saturation: conf.RPICameraSaturation,
|
||||
Sharpness: conf.RPICameraSharpness,
|
||||
Exposure: conf.RPICameraExposure,
|
||||
AWB: conf.RPICameraAWB,
|
||||
Denoise: conf.RPICameraDenoise,
|
||||
Shutter: conf.RPICameraShutter,
|
||||
Metering: conf.RPICameraMetering,
|
||||
Gain: conf.RPICameraGain,
|
||||
EV: conf.RPICameraEV,
|
||||
ROI: conf.RPICameraROI,
|
||||
TuningFile: conf.RPICameraTuningFile,
|
||||
Mode: conf.RPICameraMode,
|
||||
FPS: conf.RPICameraFPS,
|
||||
IDRPeriod: conf.RPICameraIDRPeriod,
|
||||
Bitrate: conf.RPICameraBitrate,
|
||||
Profile: conf.RPICameraProfile,
|
||||
Level: conf.RPICameraLevel,
|
||||
AfMode: conf.RPICameraAfMode,
|
||||
AfRange: conf.RPICameraAfRange,
|
||||
AfSpeed: conf.RPICameraAfSpeed,
|
||||
LensPosition: conf.RPICameraLensPosition,
|
||||
AfWindow: conf.RPICameraAfWindow,
|
||||
},
|
||||
s)
|
||||
}
|
||||
|
@ -3,7 +3,8 @@ CFLAGS = \
|
||||
-Werror \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-Wno-unused-parameter
|
||||
-Wno-unused-parameter \
|
||||
-Wno-unused-result
|
||||
|
||||
CXXFLAGS = \
|
||||
-Ofast \
|
||||
@ -11,6 +12,7 @@ CXXFLAGS = \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-Wno-unused-parameter \
|
||||
-Wno-unused-result \
|
||||
-std=c++17 \
|
||||
$$(pkg-config --cflags libcamera)
|
||||
|
||||
@ -24,7 +26,7 @@ OBJS = \
|
||||
encoder.o \
|
||||
main.o \
|
||||
parameters.o \
|
||||
roi.o \
|
||||
window.o \
|
||||
sensor_mode.o
|
||||
|
||||
all: exe
|
||||
|
@ -334,6 +334,71 @@ bool camera_start(camera_t *cam) {
|
||||
int64_t frame_time = 1000000 / camp->params->fps;
|
||||
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);
|
||||
if (res != 0) {
|
||||
set_error("Camera.start() failed");
|
||||
|
@ -39,7 +39,7 @@ bool parameters_load(parameters_t *params) {
|
||||
params->ev = atof(getenv("EV"));
|
||||
|
||||
if (strlen(getenv("ROI")) != 0) {
|
||||
bool ok = roi_load(getenv("ROI"), ¶ms->roi);
|
||||
bool ok = window_load(getenv("ROI"), ¶ms->roi);
|
||||
if (!ok) {
|
||||
set_error("invalid ROI");
|
||||
return false;
|
||||
@ -85,5 +85,20 @@ bool parameters_load(parameters_t *params) {
|
||||
params->buffer_count = 6;
|
||||
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"), ¶ms->af_window);
|
||||
if (!ok) {
|
||||
set_error("invalid AF_WINDOW");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
params->af_window = NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "roi.h"
|
||||
#include "window.h"
|
||||
#include "sensor_mode.h"
|
||||
|
||||
typedef struct {
|
||||
@ -23,7 +23,7 @@ typedef struct {
|
||||
const char *metering;
|
||||
float gain;
|
||||
float ev;
|
||||
roi_t *roi;
|
||||
window_t *roi;
|
||||
const char *tuning_file;
|
||||
sensor_mode_t *mode;
|
||||
unsigned int fps;
|
||||
@ -31,6 +31,11 @@ typedef struct {
|
||||
unsigned int bitrate;
|
||||
unsigned int profile;
|
||||
unsigned int level;
|
||||
const char *af_mode;
|
||||
const char *af_range;
|
||||
const char *af_speed;
|
||||
float lens_position;
|
||||
window_t *af_window;
|
||||
|
||||
// private
|
||||
unsigned int buffer_count;
|
||||
|
@ -1,9 +1,9 @@
|
||||
#include <stdlib.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];
|
||||
int i = 0;
|
||||
char *token = strtok((char *)encoded, ",");
|
||||
@ -21,7 +21,7 @@ bool roi_load(const char *encoded, roi_t **mode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*mode = malloc(sizeof(roi_t));
|
||||
*mode = malloc(sizeof(window_t));
|
||||
(*mode)->x = vals[0];
|
||||
(*mode)->y = vals[1];
|
||||
(*mode)->width = vals[2];
|
@ -1,5 +1,5 @@
|
||||
#ifndef __ROI_H__
|
||||
#define __ROI_H__
|
||||
#ifndef __WINDOW_H__
|
||||
#define __WINDOW_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
@ -8,8 +8,8 @@ typedef struct {
|
||||
float y;
|
||||
float width;
|
||||
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
|
@ -2,28 +2,33 @@ package rpicamera
|
||||
|
||||
// Params is a set of camera parameters.
|
||||
type Params struct {
|
||||
CameraID int
|
||||
Width int
|
||||
Height int
|
||||
HFlip bool
|
||||
VFlip bool
|
||||
Brightness float64
|
||||
Contrast float64
|
||||
Saturation float64
|
||||
Sharpness float64
|
||||
Exposure string
|
||||
AWB string
|
||||
Denoise string
|
||||
Shutter int
|
||||
Metering string
|
||||
Gain float64
|
||||
EV float64
|
||||
ROI string
|
||||
TuningFile string
|
||||
Mode string
|
||||
FPS int
|
||||
IDRPeriod int
|
||||
Bitrate int
|
||||
Profile string
|
||||
Level string
|
||||
CameraID int
|
||||
Width int
|
||||
Height int
|
||||
HFlip bool
|
||||
VFlip bool
|
||||
Brightness float64
|
||||
Contrast float64
|
||||
Saturation float64
|
||||
Sharpness float64
|
||||
Exposure string
|
||||
AWB string
|
||||
Denoise string
|
||||
Shutter int
|
||||
Metering string
|
||||
Gain float64
|
||||
EV float64
|
||||
ROI string
|
||||
TuningFile string
|
||||
Mode string
|
||||
FPS int
|
||||
IDRPeriod int
|
||||
Bitrate int
|
||||
Profile string
|
||||
Level string
|
||||
AfMode string
|
||||
AfRange string
|
||||
AfSpeed string
|
||||
LensPosition float64
|
||||
AfWindow string
|
||||
}
|
||||
|
@ -145,6 +145,11 @@ func New(
|
||||
"BITRATE=" + strconv.FormatInt(int64(params.Bitrate), 10),
|
||||
"PROFILE=" + params.Profile,
|
||||
"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)
|
||||
|
@ -327,6 +327,24 @@ paths:
|
||||
rpiCameraProfile: main
|
||||
# H264 level
|
||||
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.
|
||||
# SHA256-hashed values can be inserted with the "sha256:" prefix.
|
||||
|
Loading…
Reference in New Issue
Block a user