~martijnbraam/public-inbox

Megapixels: Introduce a memory subsystem for saving images v1 PROPOSED

Michal Ciesielski: 1
 Introduce a memory subsystem for saving images

 6 files changed, 82 insertions(+), 6 deletions(-)
#375143 alpine.yml failed
#375144 arch.yml failed
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~martijnbraam/public-inbox/patches/16090/mbox | git am -3
Learn more about email & git

[PATCH Megapixels] Introduce a memory subsystem for saving images Export this patch

From: mronetwo <ciesielskimm@gmail.com>

---
It would be good to have a memory subsystem for the images memory. That way there is no malloc/free
juggling. The memory can stay allocated for the entirety of the app running - no need to call free.
In the future we can hold images in that memory for compositing. That will be way faster from that
memory instead of writing each file to persistent storage. Hope this fits into the vision behind
this project.

 io_pipeline.c      |  9 ++++++---
 main.c             |  6 ++++++
 memory.c           | 34 ++++++++++++++++++++++++++++++++++
 memory.h           | 21 +++++++++++++++++++++
 meson.build        | 16 +++++++++++++++-
 process_pipeline.c |  2 --
 6 files changed, 82 insertions(+), 6 deletions(-)
 create mode 100644 memory.c
 create mode 100644 memory.h

diff --git a/io_pipeline.c b/io_pipeline.c
index e7b2ca9..2ee80c5 100644
--- a/io_pipeline.c
+++ b/io_pipeline.c
@@ -4,6 +4,8 @@
#include "camera.h"
#include "pipeline.h"
#include "process_pipeline.h"
#include "memory.h"

#include <string.h>
#include <glib.h>
#include <fcntl.h>
@@ -12,6 +14,7 @@
#include <assert.h>
#include <stdio.h>


struct media_link_info {
	unsigned int source_entity_id;
	unsigned int target_entity_id;
@@ -408,13 +411,13 @@ on_frame(MPImage image, void *data)
	}

	// Copy from the camera buffer
	uint8_t* prev_frame = mem_get_active_slot();
	size_t size =
		mp_pixel_format_width_to_bytes(image.pixel_format, image.width) *
		image.height;
	uint8_t *buffer = malloc(size);
	memcpy(buffer, image.data, size);
	memcpy(mem_get_next_slot(), image.data, size);

	image.data = buffer;
	image.data = prev_frame;

	// Send the image off for processing
	mp_process_pipeline_process_image(image);
diff --git a/main.c b/main.c
index 675f565..3190b88 100644
--- a/main.c
+++ b/main.c
@@ -20,6 +20,7 @@
#include "camera_config.h"
#include "quickpreview.h"
#include "io_pipeline.h"
#include "memory.h"

enum user_control { USER_CONTROL_ISO, USER_CONTROL_SHUTTER };

@@ -513,6 +514,11 @@ on_control_slider_changed(GtkAdjustment *widget, gpointer user_data)
int
main(int argc, char *argv[])
{
	const int memory_size = (16 * 1024 * 1024);
	const int images_slots = 2;
	mem_init_images_memory(
		malloc(memory_size), memory_size, (memory_size/images_slots), images_slots);

	if (!mp_load_config())
		return 1;

diff --git a/memory.c b/memory.c
new file mode 100644
index 0000000..98407f9
--- /dev/null
+++ b/memory.c
@@ -0,0 +1,34 @@
#include "memory.h"

#include <assert.h>

static struct images_memory mem = {};

static uint8_t active_slot = 0;

void mem_init_images_memory(void* data, uint32_t total_bytes, uint32_t image_size_bytes, uint32_t image_slots)
{
	mem.memory = data;
	mem.memory_size = total_bytes;
	mem.image_size_bytes = image_size_bytes;
	mem.image_slots_count = image_slots;
}

uint8_t* mem_get_image_slot(uint8_t slot)
{
	assert(slot < mem.image_slots_count);
	return (((uint8_t*)mem.memory) + mem.image_size_bytes * slot);
}

uint8_t* mem_get_next_slot()
{
	uint8_t* slot = mem_get_image_slot(active_slot);
	active_slot += 1;
	if (active_slot >= mem.image_slots_count) active_slot = 0;
	return slot;
}

uint8_t* mem_get_active_slot()
{
	return mem_get_image_slot(active_slot);
}
diff --git a/memory.h b/memory.h
new file mode 100644
index 0000000..365640a
--- /dev/null
+++ b/memory.h
@@ -0,0 +1,21 @@
#ifndef MEMORY_H
#define MEMORY_H

#include <stdint.h>

struct images_memory {
	void* memory;
	uint32_t memory_size;
	uint32_t image_size_bytes;
	uint32_t image_slots_count;
};

void mem_init_images_memory(void* data, uint32_t total_bytes, uint32_t image_size_bytes, uint32_t image_slots);

uint8_t* mem_get_image_slot(uint8_t slot);

uint8_t* mem_get_next_slot();

uint8_t* mem_get_active_slot();

#endif  // MEMORY_H
diff --git a/meson.build b/meson.build
index 0c324bf..309f18b 100644
--- a/meson.build
+++ b/meson.build
@@ -26,7 +26,21 @@ if get_option('tiffcfapattern')
  add_global_arguments('-DLIBTIFF_CFA_PATTERN', language: 'c')
endif

executable('megapixels', 'main.c', 'ini.c', 'quickpreview.c', 'camera.c', 'device.c', 'pipeline.c', 'camera_config.c', 'io_pipeline.c', 'process_pipeline.c', 'matrix.c', resources, dependencies : [gtkdep, libm, tiff, threads], install : true)
executable(
  'megapixels',
  'main.c',
  'ini.c',
  'quickpreview.c',
  'camera.c',
  'device.c',
  'pipeline.c',
  'camera_config.c',
  'io_pipeline.c',
  'process_pipeline.c',
  'matrix.c',
  'memory.c',
  resources, dependencies : [gtkdep, libm, tiff, threads], install : true
)

install_data(['data/org.postmarketos.Megapixels.desktop'],
             install_dir : get_option('datadir') / 'applications')
diff --git a/process_pipeline.c b/process_pipeline.c
index a706176..89d2539 100644
--- a/process_pipeline.c
+++ b/process_pipeline.c
@@ -340,8 +340,6 @@ process_image(MPPipeline *pipeline, const MPImage *image)
		}
	}

	free(image->data);

	++frames_processed;
	if (captures_remaining == 0) {
		is_capturing = false;
-- 
2.25.1