diff --git a/src/io_pipeline.c b/src/io_pipeline.c index 3cd6729..9b07728 100644 --- a/src/io_pipeline.c +++ b/src/io_pipeline.c @@ -74,6 +74,32 @@ update_process_pipeline() balance_blue = (float)blue / (float)state_io.blue.max; } + mp_state_proc new_state = { + .camera = state_io.camera, + .configuration = state_io.configuration, + .burst_length = state_io.burst_length, + .preview_width = state_io.preview_width, + .preview_height = state_io.preview_height, + .device_rotation = state_io.device_rotation, + + .gain.control = state_io.gain.control, + .gain.value = state_io.gain.value, + .gain.max = state_io.gain.max, + .gain.manual = state_io.gain.manual, + + .exposure.control = state_io.exposure.control, + .exposure.value = state_io.exposure.value, + .exposure.max = state_io.exposure.max, + .exposure.manual = state_io.exposure.manual, + + .focus.control = state_io.focus.control, + .focus.value = state_io.focus.value, + .focus.max = state_io.focus.max, + .focus.manual = state_io.focus.manual, + + .balance = {balance_red, 1.0f, balance_blue}, + }; + struct mp_process_pipeline_state pipeline_state = { .camera = state_io.camera, .configuration = state_io.configuration, @@ -96,7 +122,7 @@ update_process_pipeline() .control_focus = state_io.focus.control != 0, .control_flash = true, }; - mp_process_pipeline_update_state(&pipeline_state); + mp_process_pipeline_update_state(&new_state); } static void @@ -245,7 +271,7 @@ on_frame(MPBuffer buffer, void *_data) if (!check_window_active()) { return; } - + // Only update controls right after a frame was captured update_controls(); @@ -360,8 +386,16 @@ init_controls() state_io.gain.manual = mp_camera_control_get_bool(state_io.camera, V4L2_CID_AUTOGAIN) == 0; - state_io.exposure.value = - mp_camera_control_get_int32(state_io.camera, V4L2_CID_EXPOSURE); + if (mp_camera_query_control(state_io.camera, V4L2_CID_EXPOSURE, &control)) { + state_io.exposure.control = V4L2_CID_EXPOSURE; + state_io.exposure.max = control.max; + state_io.exposure.value = mp_camera_control_get_int32( + state_io.camera, V4L2_CID_EXPOSURE); + + } else { + state_io.exposure.control = 0; + } + state_io.exposure.manual = mp_camera_control_get_int32(state_io.camera, V4L2_CID_EXPOSURE_AUTO) == diff --git a/src/process_pipeline.c b/src/process_pipeline.c index b1bd2b2..20cec3c 100644 --- a/src/process_pipeline.c +++ b/src/process_pipeline.c @@ -39,14 +39,6 @@ libmegapixels_camera *pr_camera; static int output_buffer_width = -1; static int output_buffer_height = -1; -// static bool gain_is_manual; -static int gain; -static int gain_max; -static float balance[3] = { 1.0f, 1.0f, 1.0f }; - -static bool exposure_is_manual; -static int exposure; - static bool flash_enabled; static char capture_fname[255]; @@ -468,6 +460,24 @@ process_image_for_preview(const uint8_t *image) mp_process_pipeline_buffer_ref(output_buffer); mp_main_set_preview(output_buffer); + if (!state_proc.exposure.manual) { + int width = output_buffer_width / 3; + int height = output_buffer_height / 3; + uint32_t *center = g_malloc_n(width * height * sizeof(uint32_t), 1); + glReadPixels(width, + height, + width, + height, + GL_RGBA, + GL_UNSIGNED_BYTE, + center); + libmegapixels_aaa_software_statistics( + center, width, height, state_proc.stats); + printf("STAT: %d %d\n", + state_proc.stats->exposure, + state_proc.stats->whitebalance); + } + // Create a thumbnail from the preview for the last capture GdkTexture *thumb = NULL; if (state_proc.captures_remaining == 1) { @@ -571,7 +581,7 @@ process_image_for_capture(const uint8_t *image, int count) static const float neutral[] = { 1.0, 1.0, 1.0 }; TIFFSetField(tif, TIFFTAG_ASSHOTNEUTRAL, 3, neutral); - TIFFSetField(tif, TIFFTAG_ANALOGBALANCE, 3, balance); + TIFFSetField(tif, TIFFTAG_ANALOGBALANCE, 3, state_proc.balance); // Write black thumbnail, only windows uses this { @@ -643,7 +653,7 @@ process_image_for_capture(const uint8_t *image, int count) // Add an EXIF block to the tiff TIFFCreateEXIFDirectory(tif); // 1 = manual, 2 = full auto, 3 = aperture priority, 4 = shutter priority - if (!exposure_is_manual) { + if (!state_proc.exposure.manual) { TIFFSetField(tif, EXIFTAG_EXPOSUREPROGRAM, 2); } else { TIFFSetField(tif, EXIFTAG_EXPOSUREPROGRAM, 1); @@ -945,44 +955,51 @@ mod(int a, int b) } static void -update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state) +update_state(MPPipeline *pipeline, const mp_state_proc *new_state) { - state_proc.configuration = state->configuration; - state_proc.camera = state->camera; + state_proc.configuration = new_state->configuration; + state_proc.camera = new_state->camera; + + state_proc.gain.control = new_state->gain.control; + state_proc.gain.value = new_state->gain.value; + state_proc.gain.max = new_state->gain.max; + state_proc.gain.manual = new_state->gain.manual; + + state_proc.exposure.control = new_state->exposure.control; + state_proc.exposure.value = new_state->exposure.value; + state_proc.exposure.max = new_state->exposure.max; + state_proc.exposure.manual = new_state->exposure.manual; + + state_proc.focus.control = new_state->focus.control; + state_proc.focus.value = new_state->focus.value; + state_proc.focus.max = new_state->focus.max; + state_proc.focus.manual = new_state->focus.manual; const bool output_changed = !libmegapixels_mode_equals(state_proc.mode, - state->camera->current_mode) || - state_proc.preview_width != state->preview_width || - state_proc.preview_height != state->preview_height || - state_proc.device_rotation != state->device_rotation; + new_state->camera->current_mode) || + state_proc.preview_width != new_state->preview_width || + state_proc.preview_height != new_state->preview_height || + state_proc.device_rotation != new_state->device_rotation; bool format_changed = state_proc.mode == NULL; - if (!format_changed && - state_proc.mode->v4l_pixfmt != state->camera->current_mode->v4l_pixfmt) { + if (!format_changed && state_proc.mode->v4l_pixfmt != + new_state->camera->current_mode->v4l_pixfmt) { format_changed = true; } - if (state_proc.mode == NULL) { - state_proc.mode = state->camera->current_mode; - } - state_proc.mode = state->camera->current_mode; + state_proc.mode = new_state->camera->current_mode; - state_proc.preview_width = state->preview_width; - state_proc.preview_height = state->preview_height; + state_proc.preview_width = new_state->preview_width; + state_proc.preview_height = new_state->preview_height; - state_proc.device_rotation = state->device_rotation; - state_proc.burst_length = state->burst_length; + state_proc.device_rotation = new_state->device_rotation; + state_proc.burst_length = new_state->burst_length; - state_proc.gain.manual = state->gain_is_manual; - state_proc.gain.value = state->gain; - state_proc.gain.max = state->gain_max; - state_proc.balance[0] = state->balance_red; - state_proc.balance[2] = state->balance_blue; - - exposure_is_manual = state->exposure_is_manual; - exposure = state->exposure; + state_proc.balance[0] = new_state->balance[0]; + state_proc.balance[1] = new_state->balance[1]; + state_proc.balance[2] = new_state->balance[2]; if (output_changed) { state_proc.camera_rotation = mod( @@ -991,32 +1008,32 @@ update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state on_output_changed(format_changed); } - mp_state_main new_state = { + mp_state_main new_main = { .camera = pr_camera, - .gain_is_manual = state->gain_is_manual, - .gain = gain, - .gain_max = gain_max, - .exposure_is_manual = exposure_is_manual, - .exposure = exposure, - .has_auto_focus_continuous = state->has_auto_focus_continuous, - .has_auto_focus_start = state->has_auto_focus_start, + .gain_is_manual = new_state->gain.manual, + .gain = state_proc.gain.value, + .gain_max = state_proc.gain.max, + .exposure_is_manual = state_proc.exposure.manual, + .exposure = state_proc.exposure.value, + .has_auto_focus_continuous = false, + .has_auto_focus_start = false, .preview_buffer_width = output_buffer_width, .preview_buffer_height = output_buffer_height, - .control_gain = state->control_gain, - .control_exposure = state->control_exposure, - .control_focus = state->control_focus, - .control_flash = state->control_flash, + .control_gain = new_state->gain.control != 0, + .control_exposure = state_proc.exposure.control != 0, + .control_focus = state_proc.focus.control != 0, + .control_flash = false, }; - mp_main_update_state(&new_state); + mp_main_update_state(&new_main); } void -mp_process_pipeline_update_state(const struct mp_process_pipeline_state *new_state) +mp_process_pipeline_update_state(const mp_state_proc *new_state) { mp_pipeline_invoke(pipeline, (MPPipelineCallback)update_state, new_state, - sizeof(struct mp_process_pipeline_state)); + sizeof(mp_state_proc)); } // GTK4 seems to require this diff --git a/src/process_pipeline.h b/src/process_pipeline.h index 5b53ca5..88811f4 100644 --- a/src/process_pipeline.h +++ b/src/process_pipeline.h @@ -1,6 +1,7 @@ #pragma once #include "camera.h" +#include "state.h" #include typedef struct _GdkSurface GdkSurface; @@ -48,7 +49,7 @@ void mp_process_pipeline_init_gl(GdkSurface *window); void mp_process_pipeline_process_image(MPBuffer buffer); void mp_process_pipeline_capture(); -void mp_process_pipeline_update_state(const struct mp_process_pipeline_state *state); +void mp_process_pipeline_update_state(const mp_state_proc *new_state); typedef struct _MPProcessPipelineBuffer MPProcessPipelineBuffer; diff --git a/src/state.h b/src/state.h index 34300d1..0e68e32 100644 --- a/src/state.h +++ b/src/state.h @@ -77,6 +77,7 @@ typedef struct state_proc { libmegapixels_devconfig *configuration; libmegapixels_camera *camera; libmegapixels_mode *mode; + libmegapixels_aaa_stats *stats; int burst_length; int captures_remaining;