diff --git a/device/camera/camera.h b/device/camera/camera.h index d2dd5bb..a10faeb 100644 --- a/device/camera/camera.h +++ b/device/camera/camera.h @@ -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); diff --git a/device/camera/camera_input.c b/device/camera/camera_input.c index 99a5b8c..3859e16 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(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) { diff --git a/device/camera/camera_output.c b/device/camera/camera_output.c index 02f8a7e..255a327 100644 --- a/device/camera/camera_output.c +++ b/device/camera/camera_output.c @@ -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); } } diff --git a/device/camera/camera_pipeline.c b/device/camera/camera_pipeline.c index 8244c0f..1ba0e29 100644 --- a/device/camera/camera_pipeline.c +++ b/device/camera/camera_pipeline.c @@ -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; } diff --git a/device/camera/camera_rescaller.c b/device/camera/camera_rescaller.c index 59d7523..49f8013 100644 --- a/device/camera/camera_rescaller.c +++ b/device/camera/camera_rescaller.c @@ -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)