Skip to content

Map to shared memory #927

@kodonnell

Description

@kodonnell

Is your feature request related to a problem? Please describe.
I currently have a use case where I'd like multiple (python) processes to access the stream - e.g. one running machine learning, and one providing a live stream. I know I can do this as-is in a single process (main + lores, different encoders etc.) but experience tells me that this means you often end up mixing code (e.g. your machine learning code now has a webserver in it), and mixing patterns (e.g. async and non-async for machine learning / web server has been fun in the past). You also end up managing separate processes with exclusive access to the camera and ensuring they're not running concurrently. And single mega-processes are trickier to dev/debug ... not only are they more complex with lots of moving parts, but things can contend in unusual ways (and you have to be careful not to block the main picamera loop or you'll miss frames) ... but you've got to run on a pi. (I.e. if we're using /dev/shm I could just generate fake frames and all my client code wouldn't know the difference ... which I've done before with mock video on disk, but it's still a bit coupled.)

Describe the solution you'd like
What I think might be 'best' is a single camera service on the host, and all it does is spit the main/lores data to shared memory (and optionally record to disk if you want that). Then any process (in any language) can do what they want with the frames. I've implemented this as a basic memory mapped pseudo ring buffer using posix_ipc - and I can write 1080x1920x3 arrays on a pi zero 2w in about 6ms. So that'll work. I also have a need for buffering, so I keep the last N frames in the buffer ... and this solution gives me that for free. (Put another way, I'm not worried about excess memory as I'm already doing that.) However, I suspect I'm doing unnecessary memory copies, as picamera is also copying memory around (and also using mmaps etc.) - and I suspect picamera and I are both buffering the same thing. (Unlikely to be a major performance/memory hit.)

So, the request: is there currently an easy way to replace the allocators inside of picamera2 to use my own on /dev/shm, in a way I could access nicely from other processes? I can see there are definitely allocators etc. - I'm just not sure if they're as generic as I want, or which one to start with. I current serialize/deserialize the various independent things into a single frame (i.e. main + lores + metadata), but individual buffers would be fine instead as long as they're relatable in some way (e.g. by frame index or capture timestamp).

I am not suggesting building a generic RPC solution in picamera2 etc. - that can happen elsewhere, and is more complicated (what if two processes want cameras that are configured differently? etc.). Just whether I can use my own allocator in /dev/shm that would support that.

Describe alternatives you've considered
I don't think this is too relevant beyond what I've covered. All other IPC solutions will still involve copies, so it comes back to the allocator. Probably the main alternative would be going this in libcamera as the source for getting frames into /dev/shm, and python is just a consumer. But that won't be easy (for me at least). The other alternative is sticking with what I've got ... it should be fine.

Additional context
Not really. The main use will be streaming machine learning sized frames (i.e. low res) around, some going to machine learning (potentially multiple models), some to configuration, and maybe some being recorded. Performance, power consumption, and nice code are high priority, memory utilisation not so much (beyond limits of the Zero 2 W).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions