camera: improve resolution scaling for non-block camera inputs

This commit is contained in:
Kamil Trzcinski 2023-03-02 12:54:41 +01:00
parent abacfe89ea
commit edba5098d2
4 changed files with 39 additions and 21 deletions

View File

@ -10,6 +10,9 @@
#define CAMERA_DEVICE_CAMERA 0 #define CAMERA_DEVICE_CAMERA 0
#define CAMERA_OPTIONS_LENGTH 4096 #define CAMERA_OPTIONS_LENGTH 4096
#define MAX_RESCALLER_SIZE 1920
#define RESCALLER_BLOCK_SIZE 32
typedef enum { typedef enum {
CAMERA_V4L2 = 0, CAMERA_V4L2 = 0,
CAMERA_LIBCAMERA, CAMERA_LIBCAMERA,
@ -96,4 +99,4 @@ buffer_list_t *camera_configure_isp(camera_t *camera, buffer_list_t *src_capture
buffer_list_t *camera_configure_decoder(camera_t *camera, buffer_list_t *src_capture); buffer_list_t *camera_configure_decoder(camera_t *camera, buffer_list_t *src_capture);
buffer_list_t *camera_configure_rescaller(camera_t *camera, buffer_list_t *src_capture, const char *name, unsigned target_height, unsigned formats[]); buffer_list_t *camera_configure_rescaller(camera_t *camera, buffer_list_t *src_capture, const char *name, unsigned target_height, unsigned formats[]);
int camera_configure_output(camera_t *camera, buffer_list_t *camera_capture, const char *name, camera_output_options_t *options, unsigned formats[], link_callbacks_t callbacks, device_t **device); int camera_configure_output(camera_t *camera, buffer_list_t *camera_capture, const char *name, camera_output_options_t *options, unsigned formats[], link_callbacks_t callbacks, device_t **device);
bool camera_get_scaled_resolution(buffer_format_t capture_format, camera_output_options_t *options, buffer_format_t *format); bool camera_get_scaled_resolution(buffer_format_t capture_format, camera_output_options_t *options, buffer_format_t *format, int align_size);

View File

@ -80,11 +80,11 @@ static int camera_configure_input_libcamera(camera_t *camera)
bool found = false; bool found = false;
found = camera_get_scaled_resolution(capture_fmt, &camera->options.snapshot, &capture_fmt); found = camera_get_scaled_resolution(capture_fmt, &camera->options.snapshot, &capture_fmt, 1);
if (!found) if (!found)
found = camera_get_scaled_resolution(capture_fmt, &camera->options.stream, &capture_fmt); found = camera_get_scaled_resolution(capture_fmt, &camera->options.stream, &capture_fmt, 1);
if (!found) if (!found)
found = camera_get_scaled_resolution(capture_fmt, &camera->options.video, &capture_fmt); found = camera_get_scaled_resolution(capture_fmt, &camera->options.video, &capture_fmt, 1);
buffer_list_t *camera_capture = device_open_buffer_list(camera->camera, true, capture_fmt, true); buffer_list_t *camera_capture = device_open_buffer_list(camera->camera, true, capture_fmt, true);
if (!camera_capture) { if (!camera_capture) {

View File

@ -74,11 +74,18 @@ static unsigned rescalled_formats[] =
0 0
}; };
#define OUTPUT_RESCALLER_SIZE 32
int camera_configure_output(camera_t *camera, buffer_list_t *camera_capture, const char *name, camera_output_options_t *options, unsigned formats[], link_callbacks_t callbacks, device_t **device) int camera_configure_output(camera_t *camera, buffer_list_t *camera_capture, const char *name, camera_output_options_t *options, unsigned formats[], link_callbacks_t callbacks, device_t **device)
{ {
buffer_format_t selected_format = {0}; buffer_format_t selected_format = {0};
buffer_format_t rescalled_format = {0};
if (!camera_get_scaled_resolution(camera_capture->fmt, options, &selected_format)) { if (!camera_get_scaled_resolution(camera_capture->fmt, options, &selected_format, 1)) {
return 0;
}
if (!camera_get_scaled_resolution(camera_capture->fmt, options, &rescalled_format, RESCALLER_BLOCK_SIZE)) {
return 0; return 0;
} }
@ -89,15 +96,15 @@ int camera_configure_output(camera_t *camera, buffer_list_t *camera_capture, con
return 0; return 0;
} }
// Try to find exact output // Try to find exact capture
src_capture = camera_find_capture2(camera, selected_format.height, rescalled_formats); src_capture = camera_find_capture2(camera, rescalled_format.height, rescalled_formats);
// Try to re-scale output // Try to re-scale capture
if (!src_capture) { if (!src_capture) {
buffer_list_t *other_capture = camera_find_capture2(camera, 0, rescalled_formats); buffer_list_t *other_capture = camera_find_capture2(camera, 0, rescalled_formats);
if (other_capture) { if (other_capture) {
src_capture = camera_configure_rescaller(camera, other_capture, name, selected_format.height, rescalled_formats); src_capture = camera_configure_rescaller(camera, other_capture, name, rescalled_format.height, rescalled_formats);
} }
} }
@ -123,6 +130,10 @@ int camera_configure_output(camera_t *camera, buffer_list_t *camera_capture, con
// Now, do we have exact match // Now, do we have exact match
src_capture = camera_find_capture2(camera, selected_format.height, rescalled_formats); src_capture = camera_find_capture2(camera, selected_format.height, rescalled_formats);
if (!src_capture) {
src_capture = camera_find_capture2(camera, rescalled_format.height, rescalled_formats);
}
// Otherwise rescalle decoded output // Otherwise rescalle decoded output
if (!src_capture && decoded_capture) { if (!src_capture && decoded_capture) {
src_capture = camera_configure_rescaller(camera, decoded_capture, name, selected_format.height, rescalled_formats); src_capture = camera_configure_rescaller(camera, decoded_capture, name, selected_format.height, rescalled_formats);

View File

@ -10,32 +10,34 @@
#include "device/buffer_list.h" #include "device/buffer_list.h"
#include "util/http/http.h" #include "util/http/http.h"
#define MAX_RESCALLER_SIZE 1920 static unsigned camera_rescaller_align_size(unsigned size, int align_size)
#define RESCALLER_BLOCK_SIZE 32
static unsigned camera_rescaller_align_size(unsigned size, unsigned align_size)
{ {
if (align_size > 0)
return (size + align_size - 1) / align_size * align_size; return (size + align_size - 1) / align_size * align_size;
else if (align_size < 0)
return size / -align_size * -align_size;
else
return size;
} }
void camera_get_scaled_resolution2(unsigned in_width, unsigned in_height, unsigned proposed_height, unsigned *target_width, unsigned *target_height) void camera_get_scaled_resolution2(unsigned in_width, unsigned in_height, unsigned proposed_height, unsigned *target_width, unsigned *target_height, int align_size)
{ {
proposed_height = MIN(proposed_height, in_height); proposed_height = MIN(proposed_height, in_height);
*target_height = camera_rescaller_align_size(proposed_height, RESCALLER_BLOCK_SIZE); *target_height = camera_rescaller_align_size(proposed_height, align_size);
*target_height = MIN(*target_height, MAX_RESCALLER_SIZE); *target_height = MIN(*target_height, MAX_RESCALLER_SIZE);
// maintain aspect ratio on target width // maintain aspect ratio on target width
*target_width = camera_rescaller_align_size(*target_height * in_width / in_height, RESCALLER_BLOCK_SIZE); *target_width = camera_rescaller_align_size(*target_height * in_width / in_height, align_size);
// if width is larger then rescaller, try to maintain scale down height // if width is larger then rescaller, try to maintain scale down height
if (*target_width > MAX_RESCALLER_SIZE) { if (*target_width > MAX_RESCALLER_SIZE) {
*target_width = MAX_RESCALLER_SIZE; *target_width = MAX_RESCALLER_SIZE;
*target_height = camera_rescaller_align_size(*target_width * in_height / in_width, RESCALLER_BLOCK_SIZE); *target_height = camera_rescaller_align_size(*target_width * in_height / in_width, align_size);
} }
} }
bool camera_get_scaled_resolution(buffer_format_t capture_format, camera_output_options_t *options, buffer_format_t *format) bool camera_get_scaled_resolution(buffer_format_t capture_format, camera_output_options_t *options, buffer_format_t *format, int align_size)
{ {
if (options->disabled) if (options->disabled)
return false; return false;
@ -45,7 +47,8 @@ bool camera_get_scaled_resolution(buffer_format_t capture_format, camera_output_
capture_format.height, capture_format.height,
options->height, options->height,
&format->width, &format->width,
&format->height &format->height,
align_size
); );
return format->height > 0; return format->height > 0;
} }
@ -78,7 +81,8 @@ buffer_list_t *camera_try_rescaller(camera_t *camera, buffer_list_t *src_capture
camera_get_scaled_resolution2( camera_get_scaled_resolution2(
src_capture->fmt.width, src_capture->fmt.height, src_capture->fmt.width, src_capture->fmt.height,
target_height, target_height,
&target_fmt.width, &target_fmt.height &target_fmt.width, &target_fmt.height,
RESCALLER_BLOCK_SIZE
); );
buffer_list_t *rescaller_capture = device_open_buffer_list_capture( buffer_list_t *rescaller_capture = device_open_buffer_list_capture(