camera: improve resolution scaling to avoid extra rescallers

This commit is contained in:
Kamil Trzcinski 2023-02-24 19:59:42 +01:00
parent 425bbe7745
commit 6ce1869f71
5 changed files with 63 additions and 42 deletions

View File

@ -94,5 +94,5 @@ int camera_configure_pipeline(camera_t *camera, buffer_list_t *camera_capture);
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, const char *name, unsigned target_height, unsigned formats[], link_callbacks_t callbacks, device_t **device);
bool camera_get_scaled_resolution(camera_t *camera, camera_output_options_t *options, buffer_format_t *format);
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);

View File

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

View File

@ -74,20 +74,58 @@ static unsigned rescalled_formats[] =
0
};
int camera_configure_output(camera_t *camera, const char *name, unsigned target_height, 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_list_t *src_capture = camera_find_capture2(camera, target_height, formats);
buffer_format_t selected_format = {0};
if (!camera_get_scaled_resolution(camera_capture->fmt, options, &selected_format)) {
return 0;
}
// find an existing format
buffer_list_t *src_capture = camera_find_capture2(camera, selected_format.height, formats);
if (src_capture) {
camera_capture_add_callbacks(camera, src_capture, callbacks);
return 0;
}
src_capture = camera_find_capture2(camera, target_height, rescalled_formats);
// Try to find exact output
src_capture = camera_find_capture2(camera, selected_format.height, rescalled_formats);
// Try to re-scale output
if (!src_capture) {
// Try to find re-scallabe output
src_capture = camera_find_capture2(camera, 0, rescalled_formats);
if (src_capture) {
src_capture = camera_configure_rescaller(camera, src_capture, name, target_height, rescalled_formats);
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);
}
}
// Try to decode output
if (!src_capture) {
buffer_list_t *decoded_capture = NULL;
switch (camera_capture->fmt.format) {
case V4L2_PIX_FMT_SRGGB10P:
case V4L2_PIX_FMT_SGRBG10P:
case V4L2_PIX_FMT_SBGGR10P:
case V4L2_PIX_FMT_SRGGB10:
case V4L2_PIX_FMT_SGRBG10:
decoded_capture = camera_configure_isp(camera, camera_capture);
break;
case V4L2_PIX_FMT_MJPEG:
case V4L2_PIX_FMT_H264:
decoded_capture = camera_configure_decoder(camera, camera_capture);
break;
}
// Now, do we have exact match
src_capture = camera_find_capture2(camera, selected_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);
}
}

View File

@ -42,39 +42,22 @@ static link_callbacks_t video_callbacks =
.buf_lock = &video_lock
};
int camera_configure_pipeline(camera_t *camera, buffer_list_t *capture)
int camera_configure_pipeline(camera_t *camera, buffer_list_t *camera_capture)
{
if (capture) {
capture->do_timestamps = true;
camera_capture->do_timestamps = true;
switch (capture->fmt.format) {
case V4L2_PIX_FMT_SRGGB10P:
case V4L2_PIX_FMT_SGRBG10P:
case V4L2_PIX_FMT_SBGGR10P:
case V4L2_PIX_FMT_SRGGB10:
case V4L2_PIX_FMT_SGRBG10:
camera_configure_isp(camera, capture);
break;
case V4L2_PIX_FMT_MJPEG:
case V4L2_PIX_FMT_H264:
camera_configure_decoder(camera, capture);
break;
}
}
if (!camera->options.snapshot.disabled && camera_configure_output(
camera, "SNAPSHOT", camera->options.snapshot.height, snapshot_formats, snapshot_callbacks, &camera->codec_snapshot) < 0) {
if (camera_configure_output(camera, camera_capture, "SNAPSHOT", &camera->options.snapshot,
snapshot_formats, snapshot_callbacks, &camera->codec_snapshot) < 0) {
return -1;
}
if (!camera->options.stream.disabled && camera_configure_output(
camera, "STREAM", camera->options.stream.height, snapshot_formats, stream_callbacks, &camera->codec_stream) < 0) {
if (camera_configure_output(camera, camera_capture, "STREAM", &camera->options.stream,
snapshot_formats, stream_callbacks, &camera->codec_stream) < 0) {
return -1;
}
if (!camera->options.video.disabled && camera_configure_output(
camera, "VIDEO", camera->options.video.height, video_formats, video_callbacks, &camera->codec_video) < 0) {
if (camera_configure_output(camera, camera_capture, "VIDEO", &camera->options.video,
video_formats, video_callbacks, &camera->codec_video) < 0) {
return -1;
}

View File

@ -18,7 +18,7 @@ static unsigned camera_rescaller_align_size(unsigned size, unsigned align_size)
return (size + align_size - 1) / align_size * align_size;
}
static 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)
{
proposed_height = MIN(proposed_height, in_height);
@ -35,19 +35,19 @@ static void camera_get_scaled_resolution2(unsigned in_width, unsigned in_height,
}
}
bool camera_get_scaled_resolution(camera_t *camera, 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)
{
if (options->disabled)
return false;
camera_get_scaled_resolution2(
camera->options.width,
camera->options.height,
capture_format.width,
capture_format.height,
options->height,
&format->width,
&format->height
);
return true;
return format->height > 0;
}
buffer_list_t *camera_try_rescaller(camera_t *camera, buffer_list_t *src_capture, const char *name, unsigned target_height, unsigned target_format)