Process pipeline refactoring

This commit is contained in:
Martijn Braam
2023-07-20 17:40:00 +02:00
parent 2a7a5d37e6
commit 6e8293116b
6 changed files with 130 additions and 183 deletions

View File

@@ -75,6 +75,7 @@ update_process_pipeline()
struct mp_process_pipeline_state pipeline_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,
@@ -454,7 +455,7 @@ update_state(MPPipeline *pipeline, const struct mp_io_pipeline_state *state)
init_controls();
}
}
state_io.configuration = state->configuration;
state_io.burst_length = state->burst_length;
state_io.preview_width = state->preview_width;
state_io.preview_height = state->preview_height;

View File

@@ -6,6 +6,7 @@
struct mp_io_pipeline_state {
libmegapixels_camera *camera;
libmegapixels_devconfig *configuration;
int burst_length;

View File

@@ -95,6 +95,7 @@ update_io_pipeline()
{
struct mp_io_pipeline_state io_state = {
.camera = state.camera,
.configuration = state.configuration,
.burst_length = state.burst_length,
.preview_width = state.preview_width,
.preview_height = state.preview_height,

View File

@@ -4,6 +4,7 @@
#include "io_pipeline.h"
#include "main.h"
#include "pipeline.h"
#include "state.h"
#include "zbar_pipeline.h"
#include <assert.h>
#include <gtk/gtk.h>
@@ -25,6 +26,7 @@ static const float colormatrix_srgb[] = { 3.2409f, -1.5373f, -0.4986f,
0.0556f, -0.2039f, 1.0569f };
static MPPipeline *pipeline;
mp_state_proc state_proc;
static char burst_dir[23];
@@ -33,17 +35,6 @@ static volatile int frames_processed = 0;
static volatile int frames_received = 0;
libmegapixels_camera *pr_camera;
libmegapixels_mode *mode;
static int camera_rotation;
static int burst_length;
static int captures_remaining = 0;
static int preview_width;
static int preview_height;
static int device_rotation;
static int output_buffer_width = -1;
static int output_buffer_height = -1;
@@ -237,9 +228,7 @@ void
mp_process_pipeline_start()
{
pipeline = mp_pipeline_new();
mp_pipeline_invoke(pipeline, setup, NULL, 0);
mp_zbar_pipeline_start();
}
@@ -247,7 +236,6 @@ void
mp_process_pipeline_stop()
{
mp_pipeline_free(pipeline);
mp_zbar_pipeline_stop();
}
@@ -442,17 +430,19 @@ process_image_for_preview(const uint8_t *image)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_LUMINANCE,
libmegapixels_mode_width_to_bytes(mode->format, mode->width) +
libmegapixels_mode_width_to_padding(mode->format,
mode->width),
mode->height,
0,
GL_LUMINANCE,
GL_UNSIGNED_BYTE,
image);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_LUMINANCE,
libmegapixels_mode_width_to_bytes(state_proc.mode->format,
state_proc.mode->width) +
libmegapixels_mode_width_to_padding(state_proc.mode->format,
state_proc.mode->width),
state_proc.mode->height,
0,
GL_LUMINANCE,
GL_UNSIGNED_BYTE,
image);
check_gl();
gles2_debayer_process(
@@ -480,7 +470,7 @@ process_image_for_preview(const uint8_t *image)
// Create a thumbnail from the preview for the last capture
GdkTexture *thumb = NULL;
if (captures_remaining == 1) {
if (state_proc.captures_remaining == 1) {
printf("Making thumbnail\n");
size_t size = output_buffer_width * output_buffer_height *
@@ -541,26 +531,27 @@ process_image_for_capture(const uint8_t *image, int count)
// Define TIFF thumbnail
TIFFSetField(tif, TIFFTAG_SUBFILETYPE, 1);
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, mode->width >> 4);
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, mode->height >> 4);
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, state_proc.mode->width >> 4);
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, state_proc.mode->height >> 4);
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
TIFFSetField(tif, TIFFTAG_MAKE, "MAKE"); // TODO: fix
TIFFSetField(tif, TIFFTAG_MODEL, "MODEL");
TIFFSetField(tif, TIFFTAG_MAKE, state_proc.configuration->make);
TIFFSetField(tif, TIFFTAG_MODEL, state_proc.configuration->model);
uint16_t orientation;
if (camera_rotation == 0) {
orientation =
mode->mirrored ? ORIENTATION_TOPRIGHT : ORIENTATION_TOPLEFT;
} else if (camera_rotation == 90) {
orientation =
mode->mirrored ? ORIENTATION_RIGHTBOT : ORIENTATION_LEFTBOT;
} else if (camera_rotation == 180) {
orientation =
mode->mirrored ? ORIENTATION_BOTLEFT : ORIENTATION_BOTRIGHT;
if (state_proc.device_rotation == 0) {
orientation = state_proc.mode->mirrored ? ORIENTATION_TOPRIGHT :
ORIENTATION_TOPLEFT;
} else if (state_proc.device_rotation == 90) {
orientation = state_proc.mode->mirrored ? ORIENTATION_RIGHTBOT :
ORIENTATION_LEFTBOT;
} else if (state_proc.device_rotation == 180) {
orientation = state_proc.mode->mirrored ? ORIENTATION_BOTLEFT :
ORIENTATION_BOTRIGHT;
} else {
orientation =
mode->mirrored ? ORIENTATION_LEFTTOP : ORIENTATION_RIGHTTOP;
orientation = state_proc.mode->mirrored ? ORIENTATION_LEFTTOP :
ORIENTATION_RIGHTTOP;
}
TIFFSetField(tif, TIFFTAG_ORIENTATION, orientation);
TIFFSetField(tif, TIFFTAG_DATETIME, datetime);
@@ -574,98 +565,19 @@ process_image_for_capture(const uint8_t *image, int count)
char uniquecameramodel[255];
sprintf(uniquecameramodel,
"%s %s",
"MAKE", // TODO: fix
"MODEL");
state_proc.configuration->make,
state_proc.configuration->model);
TIFFSetField(tif, TIFFTAG_UNIQUECAMERAMODEL, uniquecameramodel);
// Color matrices
/*
if (pr_camera->calibration.color_matrix_1[0]) {
TIFFSetField(tif,
TIFFTAG_COLORMATRIX1,
9,
pr_camera->calibration.color_matrix_1);
} else if (pr_camera->colormatrix[0]) {
TIFFSetField(tif, TIFFTAG_COLORMATRIX1, 9, pr_camera->colormatrix);
} else {
TIFFSetField(tif, TIFFTAG_COLORMATRIX1, 9, colormatrix_srgb);
}
if (pr_camera->calibration.color_matrix_2[0]) {
TIFFSetField(tif,
TIFFTAG_COLORMATRIX2,
9,
pr_camera->calibration.color_matrix_2);
}
if (pr_camera->calibration.forward_matrix_1[0]) {
TIFFSetField(tif,
TIFFTAG_FORWARDMATRIX1,
9,
pr_camera->calibration.forward_matrix_1);
} else if (pr_camera->forwardmatrix[0]) {
TIFFSetField(tif, TIFFTAG_FORWARDMATRIX1, 9,
pr_camera->forwardmatrix);
}
if (pr_camera->calibration.forward_matrix_2[0]) {
TIFFSetField(tif,
TIFFTAG_FORWARDMATRIX2,
9,
pr_camera->calibration.forward_matrix_2);
}
static const float neutral[] = { 1.0, 1.0, 1.0 };
TIFFSetField(tif, TIFFTAG_ASSHOTNEUTRAL, 3, neutral);
if (pr_camera->calibration.illuminant_1) {
TIFFSetField(tif,
TIFFTAG_CALIBRATIONILLUMINANT1,
pr_camera->calibration.illuminant_1);
} else {
TIFFSetField(tif, TIFFTAG_CALIBRATIONILLUMINANT1, 21);
}
if (pr_camera->calibration.illuminant_2) {
TIFFSetField(tif,
TIFFTAG_CALIBRATIONILLUMINANT2,
pr_camera->calibration.illuminant_2);
}
if (pr_camera->calibration.tone_curve_length) {
TIFFSetField(tif,
DCPTAG_PROFILE_TONE_CURVE,
pr_camera->calibration.tone_curve_length,
pr_camera->calibration.tone_curve);
}
if (pr_camera->calibration.hue_sat_map_dims[0]) {
TIFFSetField(tif,
DCPTAG_PROFILE_HUE_SAT_MAP_DIMS,
3,
pr_camera->calibration.hue_sat_map_dims);
TIFFSetField(tif,
DCPTAG_PROFILE_HUE_SAT_MAP_DATA_1,
pr_camera->calibration.hue_sat_map_dims[0] *
pr_camera->calibration.hue_sat_map_dims[1] *
pr_camera->calibration.hue_sat_map_dims[2] * 3,
pr_camera->calibration.hue_sat_map_data_1);
if (pr_camera->calibration.hue_sat_map_data_2 != NULL) {
TIFFSetField(
tif,
DCPTAG_PROFILE_HUE_SAT_MAP_DATA_2,
pr_camera->calibration.hue_sat_map_dims[0] *
pr_camera->calibration.hue_sat_map_dims[1] *
pr_camera->calibration.hue_sat_map_dims[2] *
3, pr_camera->calibration.hue_sat_map_data_2);
}
}
*/
TIFFSetField(tif, TIFFTAG_ANALOGBALANCE, 3, balance);
// Write black thumbnail, only windows uses this
{
unsigned char *buf =
(unsigned char *)calloc(1, (mode->width >> 4) * 3);
for (int row = 0; row < (mode->height >> 4); row++) {
unsigned char *buf = (unsigned char *)calloc(
1, (state_proc.mode->width >> 4) * 3);
for (int row = 0; row < (state_proc.mode->height >> 4); row++) {
TIFFWriteScanline(tif, buf, row, 0);
}
free(buf);
@@ -674,11 +586,11 @@ process_image_for_capture(const uint8_t *image, int count)
// Define main photo
TIFFSetField(tif, TIFFTAG_SUBFILETYPE, 0);
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, mode->width);
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, mode->height);
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, state_proc.mode->width);
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, state_proc.mode->height);
TIFFSetField(tif,
TIFFTAG_BITSPERSAMPLE,
libmegapixels_format_bits_per_pixel(mode->format));
libmegapixels_format_bits_per_pixel(state_proc.mode->format));
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CFA);
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
@@ -692,11 +604,12 @@ process_image_for_capture(const uint8_t *image, int count)
TIFFSetField(tif,
TIFFTAG_CFAPATTERN,
4,
libmegapixels_format_cfa_pattern(mode->format));
libmegapixels_format_cfa_pattern(state_proc.mode->format));
#endif
printf("TIFF version %d\n", TIFFLIB_VERSION);
int whitelevel =
(1 << libmegapixels_format_bits_per_pixel(mode->format)) - 1;
(1 << libmegapixels_format_bits_per_pixel(state_proc.mode->format)) -
1;
TIFFSetField(tif, TIFFTAG_WHITELEVEL, 1, &whitelevel);
TIFFCheckpointDirectory(tif);
printf("Writing frame to %s\n", fname);
@@ -704,19 +617,21 @@ process_image_for_capture(const uint8_t *image, int count)
uint8_t *output_image = (uint8_t *)image;
// Repack 10-bit image from sensor format into a sequencial format
if (libmegapixels_format_bits_per_pixel(mode->format) == 10) {
output_image = malloc(libmegapixels_mode_width_to_bytes(
mode->format, mode->width) *
mode->height);
if (libmegapixels_format_bits_per_pixel(state_proc.mode->format) == 10) {
output_image = malloc(
libmegapixels_mode_width_to_bytes(state_proc.mode->format,
state_proc.mode->width) *
state_proc.mode->height);
repack_image_sequencial(image, output_image, mode);
repack_image_sequencial(image, output_image, state_proc.mode);
}
for (int row = 0; row < mode->height; row++) {
for (int row = 0; row < state_proc.mode->height; row++) {
TIFFWriteScanline(tif,
(void *)output_image +
(row * libmegapixels_mode_width_to_bytes(
mode->format, mode->width)),
state_proc.mode->format,
state_proc.mode->width)),
row,
0);
}
@@ -876,20 +791,21 @@ process_image(MPPipeline *pipeline, const MPBuffer *buffer)
clock_t t1 = clock();
#endif
size_t size =
(libmegapixels_mode_width_to_bytes(mode->format, mode->width) +
libmegapixels_mode_width_to_padding(mode->format, mode->width)) *
mode->height;
size_t size = (libmegapixels_mode_width_to_bytes(state_proc.mode->format,
state_proc.mode->width) +
libmegapixels_mode_width_to_padding(state_proc.mode->format,
state_proc.mode->width)) *
state_proc.mode->height;
uint8_t *image = malloc(size);
memcpy(image, buffer->data, size);
mp_io_pipeline_release_buffer(buffer->index);
MPZBarImage *zbar_image = mp_zbar_image_new(image,
mode->format,
mode->width,
mode->height,
camera_rotation,
mode->mirrored);
state_proc.mode->format,
state_proc.mode->width,
state_proc.mode->height,
state_proc.device_rotation,
state_proc.mode->mirrored);
mp_zbar_pipeline_process_image(mp_zbar_image_ref(zbar_image));
#ifdef PROFILE_PROCESS
@@ -898,13 +814,13 @@ process_image(MPPipeline *pipeline, const MPBuffer *buffer)
GdkTexture *thumb = process_image_for_preview(image);
if (captures_remaining > 0) {
int count = burst_length - captures_remaining;
--captures_remaining;
if (state_proc.captures_remaining > 0) {
int count = state_proc.burst_length - state_proc.captures_remaining;
--state_proc.captures_remaining;
process_image_for_capture(image, count);
if (captures_remaining == 0) {
if (state_proc.captures_remaining == 0) {
assert(thumb);
process_capture_burst(thumb);
} else {
@@ -917,7 +833,7 @@ process_image(MPPipeline *pipeline, const MPBuffer *buffer)
mp_zbar_image_unref(zbar_image);
++frames_processed;
if (captures_remaining == 0) {
if (state_proc.captures_remaining == 0) {
is_capturing = false;
}
@@ -961,7 +877,7 @@ capture()
strcpy(burst_dir, tempdir);
captures_remaining = burst_length;
state_proc.captures_remaining = state_proc.burst_length;
}
void
@@ -975,10 +891,10 @@ mp_process_pipeline_capture()
static void
on_output_changed(bool format_changed)
{
output_buffer_width = mode->width / 2;
output_buffer_height = mode->height / 2;
output_buffer_width = state_proc.mode->width / 2;
output_buffer_height = state_proc.mode->height / 2;
if (mode->rotation != 0 && mode->rotation != 180) {
if (state_proc.mode->rotation != 0 && state_proc.mode->rotation != 180) {
int tmp = output_buffer_width;
output_buffer_width = output_buffer_height;
output_buffer_height = tmp;
@@ -1004,7 +920,7 @@ on_output_changed(bool format_changed)
if (gles2_debayer)
gles2_debayer_free(gles2_debayer);
gles2_debayer = gles2_debayer_new(mode->format);
gles2_debayer = gles2_debayer_new(state_proc.mode->format);
check_gl();
gles2_debayer_use(gles2_debayer);
@@ -1013,9 +929,9 @@ on_output_changed(bool format_changed)
gles2_debayer_configure(gles2_debayer,
output_buffer_width,
output_buffer_height,
mode->width,
mode->height,
mode->rotation,
state_proc.mode->width,
state_proc.mode->height,
state_proc.mode->rotation,
0,
NULL,
0);
@@ -1031,43 +947,46 @@ mod(int a, int b)
static void
update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state)
{
const bool output_changed =
!libmegapixels_mode_equals(mode, state->camera->current_mode) ||
preview_width != state->preview_width ||
preview_height != state->preview_height ||
device_rotation != state->device_rotation;
state_proc.configuration = state->configuration;
state_proc.camera = state->camera;
bool format_changed = mode == NULL;
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;
bool format_changed = state_proc.mode == NULL;
if (!format_changed &&
mode->v4l_pixfmt != state->camera->current_mode->v4l_pixfmt) {
state_proc.mode->v4l_pixfmt != state->camera->current_mode->v4l_pixfmt) {
format_changed = true;
}
if (mode == NULL) {
mode = state->camera->current_mode;
if (state_proc.mode == NULL) {
state_proc.mode = state->camera->current_mode;
}
pr_camera = state->camera;
mode = state->camera->current_mode;
state_proc.mode = state->camera->current_mode;
preview_width = state->preview_width;
preview_height = state->preview_height;
state_proc.preview_width = state->preview_width;
state_proc.preview_height = state->preview_height;
device_rotation = state->device_rotation;
state_proc.device_rotation = state->device_rotation;
state_proc.burst_length = state->burst_length;
burst_length = state->burst_length;
// gain_is_manual = state->gain_is_manual;
gain = state->gain;
gain_max = state->gain_max;
balance[0] = state->balance_red;
balance[2] = state->balance_blue;
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;
if (output_changed) {
camera_rotation = mod(mode->rotation - device_rotation, 360);
state_proc.camera_rotation = mod(
state_proc.mode->rotation - state_proc.device_rotation, 360);
on_output_changed(format_changed);
}

View File

@@ -7,6 +7,7 @@ typedef struct _GdkSurface GdkSurface;
struct mp_process_pipeline_state {
libmegapixels_camera *camera;
libmegapixels_devconfig *configuration;
int burst_length;

View File

@@ -47,6 +47,7 @@ typedef struct cstate {
} controlstate;
typedef struct state_io {
libmegapixels_devconfig *configuration;
libmegapixels_camera *camera;
libmegapixels_mode *mode_capture;
libmegapixels_mode *mode_preview;
@@ -70,4 +71,27 @@ typedef struct state_io {
int preview_width;
int preview_height;
int device_rotation;
} mp_state_io;
} mp_state_io;
typedef struct state_proc {
libmegapixels_devconfig *configuration;
libmegapixels_camera *camera;
libmegapixels_mode *mode;
int burst_length;
int captures_remaining;
int preview_width;
int preview_height;
// Device orientation in degrees
int device_rotation;
// Camera orientation as number
int camera_rotation;
bool is_capturing;
float balance[3];
controlstate gain;
controlstate exposure;
controlstate focus;
} mp_state_proc;