diff --git a/device/camera/camera.h b/device/camera/camera.h index af2a9c0..1187609 100644 --- a/device/camera/camera.h +++ b/device/camera/camera.h @@ -10,6 +10,9 @@ #define CAMERA_DEVICE_CAMERA 0 #define CAMERA_OPTIONS_LENGTH 4096 +#define MAX_RESCALLER_SIZE 1920 +#define RESCALLER_BLOCK_SIZE 32 + typedef enum { CAMERA_V4L2 = 0, 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_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); -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); diff --git a/device/camera/camera_input.c b/device/camera/camera_input.c index 3859e16..461d12f 100644 --- a/device/camera/camera_input.c +++ b/device/camera/camera_input.c @@ -80,11 +80,11 @@ static int camera_configure_input_libcamera(camera_t *camera) 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) - 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) - 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); if (!camera_capture) { diff --git a/device/camera/camera_output.c b/device/camera/camera_output.c index 255a327..5ef5f91 100644 --- a/device/camera/camera_output.c +++ b/device/camera/camera_output.c @@ -74,11 +74,18 @@ static unsigned rescalled_formats[] = 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) { 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; } @@ -89,15 +96,15 @@ int camera_configure_output(camera_t *camera, buffer_list_t *camera_capture, con return 0; } - // Try to find exact output - src_capture = camera_find_capture2(camera, selected_format.height, rescalled_formats); + // Try to find exact capture + src_capture = camera_find_capture2(camera, rescalled_format.height, rescalled_formats); - // Try to re-scale output + // Try to re-scale capture if (!src_capture) { buffer_list_t *other_capture = camera_find_capture2(camera, 0, rescalled_formats); 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 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 if (!src_capture && decoded_capture) { src_capture = camera_configure_rescaller(camera, decoded_capture, name, selected_format.height, rescalled_formats); diff --git a/device/camera/camera_rescaller.c b/device/camera/camera_rescaller.c index 49f8013..5456886 100644 --- a/device/camera/camera_rescaller.c +++ b/device/camera/camera_rescaller.c @@ -10,32 +10,34 @@ #include "device/buffer_list.h" #include "util/http/http.h" -#define MAX_RESCALLER_SIZE 1920 -#define RESCALLER_BLOCK_SIZE 32 - -static unsigned camera_rescaller_align_size(unsigned size, unsigned align_size) +static unsigned camera_rescaller_align_size(unsigned size, int align_size) { - return (size + align_size - 1) / align_size * align_size; + if (align_size > 0) + 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); - *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); // 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 (*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) return false; @@ -45,7 +47,8 @@ bool camera_get_scaled_resolution(buffer_format_t capture_format, camera_output_ capture_format.height, options->height, &format->width, - &format->height + &format->height, + align_size ); 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( src_capture->fmt.width, src_capture->fmt.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(