From 8ccf1451ed72a2839d8d0dfe39943b82d7b93920 Mon Sep 17 00:00:00 2001 From: Benjamin Schaaf Date: Sat, 1 May 2021 21:28:02 +1000 Subject: [PATCH] Fix image capture --- src/io_pipeline.c | 2 + src/main.c | 35 ++------------ src/main.h | 7 +-- src/process_pipeline.c | 101 +++++++++++++---------------------------- 4 files changed, 40 insertions(+), 105 deletions(-) diff --git a/src/io_pipeline.c b/src/io_pipeline.c index db50cfe..08edd7e 100644 --- a/src/io_pipeline.c +++ b/src/io_pipeline.c @@ -311,6 +311,7 @@ capture(MPPipeline *pipeline, const void *data) V4L2_EXPOSURE_MANUAL); // Change camera mode for capturing + mp_process_pipeline_sync(); mp_camera_stop_capture(info->camera); mode = camera->capture_mode; @@ -448,6 +449,7 @@ on_frame(MPBuffer buffer, void * _data) } // Go back to preview mode + mp_process_pipeline_sync(); mp_camera_stop_capture(info->camera); mode = camera->preview_mode; diff --git a/src/main.c b/src/main.c index 458c32b..ae486f9 100644 --- a/src/main.c +++ b/src/main.c @@ -182,34 +182,8 @@ mp_main_set_preview(MPProcessPipelineBuffer *buffer) (GSourceFunc)set_preview, buffer, NULL); } -static void transform_centered(cairo_t *cr, uint32_t dst_width, uint32_t dst_height, - int src_width, int src_height) -{ - cairo_translate(cr, dst_width / 2, dst_height / 2); - - double scale = MIN(dst_width / (double)src_width, dst_height / (double)src_height); - cairo_scale(cr, scale, scale); - - cairo_translate(cr, -src_width / 2, -src_height / 2); -} - -void -draw_surface_scaled_centered(cairo_t *cr, uint32_t dst_width, uint32_t dst_height, - cairo_surface_t *surface) -{ - cairo_save(cr); - - int width = cairo_image_surface_get_width(surface); - int height = cairo_image_surface_get_height(surface); - transform_centered(cr, dst_width, dst_height, width, height); - - cairo_set_source_surface(cr, surface, 0, 0); - cairo_paint(cr); - cairo_restore(cr); -} - struct capture_completed_args { - cairo_surface_t *thumb; + GdkTexture *thumb; char *fname; }; @@ -218,19 +192,20 @@ capture_completed(struct capture_completed_args *args) { strncpy(last_path, args->fname, 259); - // gtk_image_set_from_surface(GTK_IMAGE(thumb_last), args->thumb); + gtk_image_set_from_paintable(GTK_IMAGE(thumb_last), + GDK_PAINTABLE(args->thumb)); gtk_spinner_stop(GTK_SPINNER(process_spinner)); gtk_stack_set_visible_child(GTK_STACK(open_last_stack), thumb_last); - cairo_surface_destroy(args->thumb); + g_object_unref(args->thumb); g_free(args->fname); return false; } void -mp_main_capture_completed(cairo_surface_t *thumb, const char *fname) +mp_main_capture_completed(GdkTexture *thumb, const char *fname) { struct capture_completed_args *args = malloc(sizeof(struct capture_completed_args)); args->thumb = thumb; diff --git a/src/main.h b/src/main.h index 720b4c5..bbebca9 100644 --- a/src/main.h +++ b/src/main.h @@ -5,8 +5,6 @@ #include "process_pipeline.h" #include "gtk/gtk.h" -#define MP_MAIN_THUMB_SIZE 24 - struct mp_main_state { const struct mp_camera_config *camera; MPCameraMode mode; @@ -28,11 +26,8 @@ struct mp_main_state { void mp_main_update_state(const struct mp_main_state *state); void mp_main_set_preview(MPProcessPipelineBuffer *buffer); -void mp_main_capture_completed(cairo_surface_t *thumb, const char *fname); +void mp_main_capture_completed(GdkTexture *thumb, const char *fname); void mp_main_set_zbar_result(MPZBarScanResult *result); int remap(int value, int input_min, int input_max, int output_min, int output_max); - -void draw_surface_scaled_centered(cairo_t *cr, uint32_t dst_width, uint32_t dst_height, - cairo_surface_t *surface); diff --git a/src/process_pipeline.c b/src/process_pipeline.c index ae8cebe..f0da6ed 100644 --- a/src/process_pipeline.c +++ b/src/process_pipeline.c @@ -40,6 +40,9 @@ static int captures_remaining = 0; static int preview_width; static int preview_height; +static int output_buffer_width = -1; +static int output_buffer_height = -1; + // static bool gain_is_manual; static int gain; static int gain_max; @@ -252,7 +255,7 @@ mp_process_pipeline_init_gl(GdkSurface *surface) mp_pipeline_invoke(pipeline, (MPPipelineCallback) init_gl, &surface, sizeof(GdkSurface *)); } -static cairo_surface_t * +static GdkTexture * process_image_for_preview(const uint8_t *image) { #ifdef PROFILE_DEBAYER @@ -300,55 +303,6 @@ process_image_for_preview(const uint8_t *image) printf("%fms\n", (float)(t2 - t1) / CLOCKS_PER_SEC * 1000); #endif - // { - // glBindTexture(GL_TEXTURE_2D, textures[1]); - // EGLImage egl_image = eglCreateImage(egl_display, egl_context, EGL_GL_TEXTURE_2D, (EGLClientBuffer)(size_t)textures[1], NULL); - - // // Make sure it's in the expected format - // int fourcc; - // eglExportDMABUFImageQueryMESA(egl_display, egl_image, &fourcc, NULL, NULL); - // assert(fourcc == DRM_FORMAT_ABGR8888); - - - // int dmabuf_fd; - // int stride, offset; - // eglExportDMABUFImageMESA(egl_display, egl_image, &dmabuf_fd, &stride, &offset); - - // int fsize = lseek(dmabuf_fd, 0, SEEK_END); - // printf("SIZE %d STRIDE %d OFFSET %d SIZE %d:%d\n", fsize, stride, offset, preview_width, preview_height); - - // size_t size = stride * preview_height; - // uint32_t *data = mmap(NULL, fsize, PROT_READ, MAP_SHARED, dmabuf_fd, 0); - // assert(data != MAP_FAILED); - - // int pixel_stride = stride / 4; - - // for (size_t y = 0; y < preview_height; ++y) { - // for (size_t x = 0; x < preview_width; ++x) { - // uint32_t p = data[x + y * pixel_stride]; - // pixels[x + y * preview_width] = p; - // // uint16_t p = data[x + y * stride]; - // // uint32_t r = (p & 0b11111); - // // uint32_t g = ((p >> 5) & 0b11111); - // // uint32_t b = ((p >> 10) & 0b11111); - // // pixels[x + y * preview_width] = (r << 16) | (g << 8) | b; - // } - // // memcpy(pixels + preview_width * y, data + stride * y, preview_width * sizeof(uint32_t)); - // } - - // { - // FILE *f = fopen("test.raw", "w"); - // fwrite(data, fsize, 1, f); - // fclose(f); - // } - - // // memcpy(pixels, data, size); - // munmap(data, size); - // close(dmabuf_fd); - // } - // glReadPixels(0, 0, preview_width, preview_height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - // check_gl(); - #ifdef RENDERDOC if(rdoc_api) rdoc_api->EndFrameCapture(NULL, NULL); #endif @@ -357,20 +311,33 @@ process_image_for_preview(const uint8_t *image) mp_main_set_preview(output_buffer); // Create a thumbnail from the preview for the last capture - cairo_surface_t *thumb = NULL; - // if (captures_remaining == 1) { - // printf("Making thumbnail\n"); - // thumb = cairo_image_surface_create( - // CAIRO_FORMAT_ARGB32, MP_MAIN_THUMB_SIZE, MP_MAIN_THUMB_SIZE); + GdkTexture *thumb = NULL; + if (captures_remaining == 1) { + printf("Making thumbnail\n"); - // cairo_t *cr = cairo_create(thumb); - // draw_surface_scaled_centered( - // cr, MP_MAIN_THUMB_SIZE, MP_MAIN_THUMB_SIZE, surface); - // cairo_destroy(cr); - // } + size_t size = output_buffer_width * output_buffer_height * sizeof(uint32_t); - // Pass processed preview to main and zbar - // mp_zbar_pipeline_process_image(cairo_surface_reference(surface)); + uint32_t *data = g_malloc_n(size, 1); + + glReadPixels(0, 0, output_buffer_width, output_buffer_height, GL_RGBA, GL_UNSIGNED_BYTE, data); + check_gl(); + + // Flip vertically + for (size_t y = 0; y < output_buffer_height / 2; ++y) { + for (size_t x = 0; x < output_buffer_width; ++x) { + uint32_t tmp = data[(output_buffer_height - y - 1) * output_buffer_width + x]; + data[(output_buffer_height - y - 1) * output_buffer_width + x] = data[y * output_buffer_width + x]; + data[y * output_buffer_width + x] = tmp; + } + } + + thumb = gdk_memory_texture_new( + output_buffer_width, + output_buffer_height, + GDK_MEMORY_R8G8B8A8, + g_bytes_new_take(data, size), + output_buffer_width * sizeof(uint32_t)); + } return thumb; } @@ -527,7 +494,7 @@ process_image_for_capture(const uint8_t *image, int count) } static void -post_process_finished(GSubprocess *proc, GAsyncResult *res, cairo_surface_t *thumb) +post_process_finished(GSubprocess *proc, GAsyncResult *res, GdkTexture *thumb) { char *stdout; g_subprocess_communicate_utf8_finish(proc, res, &stdout, NULL, NULL); @@ -550,7 +517,7 @@ post_process_finished(GSubprocess *proc, GAsyncResult *res, cairo_surface_t *thu } static void -process_capture_burst(cairo_surface_t *thumb) +process_capture_burst(GdkTexture *thumb) { time_t rawtime; time(&rawtime); @@ -615,7 +582,7 @@ process_image(MPPipeline *pipeline, const MPBuffer *buffer) MPZBarImage *zbar_image = mp_zbar_image_new(image, mode.pixel_format, mode.width, mode.height, camera->rotate, camera->mirrored); mp_zbar_pipeline_process_image(mp_zbar_image_ref(zbar_image)); - cairo_surface_t *thumb = process_image_for_preview(image); + GdkTexture *thumb = process_image_for_preview(image); if (captures_remaining > 0) { int count = burst_length - captures_remaining; @@ -646,7 +613,6 @@ mp_process_pipeline_process_image(MPBuffer buffer) { // If we haven't processed the previous frame yet, drop this one if (frames_received != frames_processed && !is_capturing) { - printf("Dropped frame at capture\n"); mp_io_pipeline_release_buffer(buffer.index); return; } @@ -682,9 +648,6 @@ mp_process_pipeline_capture() mp_pipeline_invoke(pipeline, capture, NULL, 0); } -static int output_buffer_width = -1; -static int output_buffer_height = -1; - static void on_output_changed() {