diff --git a/libpicam/picam.cpp b/libpicam/picam.cpp index 42a676d..40b8d43 100644 --- a/libpicam/picam.cpp +++ b/libpicam/picam.cpp @@ -64,6 +64,16 @@ static void check_camera_stack() exit(-1); } +static int xioctl(int fd, unsigned long ctl, void *arg) +{ + int ret, num_tries = 10; + do + { + ret = ioctl(fd, ctl, arg); + } while (ret == -1 && errno == EINTR && num_tries-- > 0); + return ret; +} + void Picam::set_exposure_to_auto() { log_debug("exposure mode: auto\n"); controls_.set(libcamera::controls::AeExposureMode, libcamera::controls::ExposureNormal); @@ -1642,6 +1652,29 @@ void Picam::setOption(PicamOption *option) this->option = option; } +void Picam::setHDR(bool enabled) { + 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, enabled }; + ok = !xioctl(fd, VIDIOC_S_CTRL, &ctrl); + close(fd); + } + if (enabled) { + if (ok) { + log_debug("HDR mode enabled\n"); + } else { + log_debug("failed to enable HDR mode\n"); + } + } +} + void stopSignalHandler(int signo) { log_debug("stop requested (signal=%d)\n", signo); Picam *picam; @@ -1686,6 +1719,9 @@ int Picam::run(int argc, char *argv[]) sigaction(SIGINT, &int_handler, NULL); sigaction(SIGTERM, &int_handler, NULL); + // HDR control must be done before opening or listing the camera + this->setHDR(this->option->video_hdr); + if (this->option->query_and_exit) { this->queryCameras(); diff --git a/libpicam/picam.hpp b/libpicam/picam.hpp index 4f8720f..f107cf1 100644 --- a/libpicam/picam.hpp +++ b/libpicam/picam.hpp @@ -185,6 +185,7 @@ class Picam { void event_loop(); void setOption(PicamOption *option); + void setHDR(bool enabled); void setupEncoder(); void modifyBuffer(CompletedRequestPtr &completed_request); int64_t get_next_video_pts_vfr(); diff --git a/picam_option/picam_option.cpp b/picam_option/picam_option.cpp index cca9c4e..6da38ea 100644 --- a/picam_option/picam_option.cpp +++ b/picam_option/picam_option.cpp @@ -127,6 +127,7 @@ void PicamOption::print_usage() { log_info(" --shutter Set shutter speed in microseconds (default: auto).\n"); log_info(" Implies --vfr.\n"); // log_info(" --iso Set ISO sensitivity (100..800) (default: auto)\n"); + log_info(" --nohdr Disable HDR mode. HDR is enabled by default on Camera Module 3.\n"); log_info(" --roi Set region of interest (crop rect) in ratio (0.0-1.0).\n"); log_info(" (default: %.0f,%.0f,%.0f,%.0f)\n", defaultOption.roi_left, defaultOption.roi_top, defaultOption.roi_width, defaultOption.roi_height); @@ -289,6 +290,7 @@ int PicamOption::parse(int argc, char **argv) { { "sharpness", required_argument, NULL, 0 }, { "autofocus-mode", required_argument, NULL, 0 }, { "lens-position", required_argument, NULL, 0 }, + { "nohdr", no_argument, NULL, 0 }, { 0, 0, 0, 0 }, }; int option_index = 0; @@ -1056,7 +1058,9 @@ int PicamOption::parse(int argc, char **argv) { video_lens_position = value; strncpy(video_autofocus_mode, "manual", sizeof(video_autofocus_mode) - 1); video_autofocus_mode[sizeof(video_autofocus_mode) - 1] = '\0'; - } + } else if (strcmp(long_options[option_index].name, "nohdr") == 0) { + video_hdr = false; + } break; case 'w': { diff --git a/picam_option/picam_option.hpp b/picam_option/picam_option.hpp index 8fc5f9b..c48919a 100644 --- a/picam_option/picam_option.hpp +++ b/picam_option/picam_option.hpp @@ -197,6 +197,9 @@ class PicamOption // 0.0 means no sharpening float video_sharpness = 0.0f; + // HDR mode for Camera Module 3 + bool video_hdr = true; + // The default is to initiate autofocus at any moment char video_autofocus_mode[11] = "continuous";