More documentation

This commit is contained in:
Martijn Braam
2023-12-04 16:35:39 +01:00
parent 89af026c8e
commit f766e71935
3 changed files with 156 additions and 1 deletions

28
docs/faq.rst Normal file
View File

@@ -0,0 +1,28 @@
Frequently Asked Questions
==========================
What is libmegapixels?
This is a library for accessing V4L2 cameras on modern ARM platforms that
use the media-request pipeline to do routing of cameras to the SoC hardware
to process the pixels in various ways. It's intended to be called instead of
opening the plain V4L2 device so it can configure the hardware to a specific
mode and then it hands over the V4L2 handles to let your application do the
normal Linux camera procedures.
What is the correct way to display the name 'libmegapixels'?
Just follow the correct grammar rules for your language. Being difficult
about the capitalisation of project names is just a massive waste of time.
How is libmegapixels different from using V4L2
Libmegapixels is just a glue layer on top of V4L2 to make writing
applications that use the new media request pipeline a lot easier. Once the
pipeline has been configured libmegapixels will just hand over a file
descriptor for a regular V4L2 device to get the frames from.
Does this mean the camera stack is completely open?
Yes, libmegapixels does not support the Android mess that is closed-source
userspace sensor drivers and also provides an open source AAA algorithm.
Using closed modules in libmegapixels is prohibited, but it's only a
library for accessing V4L2 so whatever happens in the applications is up to
the applications.

View File

@@ -13,3 +13,6 @@ media graph interface in Linux for ARM platforms with cameras.
.. toctree::
:maxdepth: 2
:caption: Contents:
overview
faq

124
docs/overview.rst Normal file
View File

@@ -0,0 +1,124 @@
Overview
========
Libmegapixels is a library for accessing V4L2 cameras in Linux. It's the camera
set-up code originally written for Megapixels but split off and improved as a
library to make it easier to debug and integrate.
The way you'd normally open a webcam in Linux and capture frames is roughly:
- Open a :code:`/dev/video*` file descriptor
- Run the :code:`VIDIOC_QUERYCAP` ioctl to check the device has the :code:`V4L2_CAP_VIDEO_CAPTURE` flag and check which methods of capturing frames are valid.
- Run the :code:`VIDIOC_S_FMT` and :code:`VIDIOC_G_FMT` ioctls a few times to narrow down a format to use.
- Set-up mmapped video capture on the device and run :code:`VIDIOC_STREAMON` to start the capture
- Get frames from the kernel
This works for UVC webcams you usually encounter on Linux devices since these are
relatively simple devices.
If you try to use the camera on a modern phone the whole workflow is completely different.
Instead of dealing with just a video device you also have to deal with
a :code:`/dev/media*` device for setting up hardware pipelines and then deal with
various :code:`/dev/v4l-subdev*` devices to configure all the nodes in that media pipeline.
One (or more) of the nodes in that media pipeline will be the regular old :code:`/dev/video*`
device again that will provide your application with the frames, but due to the way
the pipelines work a lot of the normal auto-configuration things applications do no longer work.
In the new pipelines the video device only deals with getting the video frames into
userspace. Due to this the video device does not actually know what formats and
resolutions are valid so using the old ioctls to query this information is useless.
One of the v4l-subdev devices will be representing the sensor in the device, this does know what
modes are available but to know that mode will work you need to make sure all the nodes in the
pipeline can run at that mode and all these nodes need to be manually configured. But in
reality it's even more complicated becaues this only describes what resolutions and modes
the drivers for these components support and it does not account for limitations in
the actual hardware like not all the MIPI lanes being connected between the sensor
and the SoC limiting the possible bandwidth, or even more basic bandwidth limitations
due to the length of PCB traces.
Using libmegapixels
-------------------
The solution for this mess in Megapixels which is now transferred to a library
is using config files that provide the pipeline information. This hardcodes a
series of known working modes and also provides the metadata for producing
high quality pictuers from the data coming from the pipeline.
The general use of libmegapixels is this:
.. code-block:: c
#include <libmegapixels.h>
// Create the empty device config object
libmegapixels_devconfig *config = {0};
libmegapixels_init(&config);
// Find the config file path for this device
char configpath[PATH_MAX];
int ret = libmegapixels_find_config(configpath);
// Load the config
libmegapixels_load_file(config, configpath);
// Additionally load UVC cameras with autodetection
libmegapixels_load_uvc(config);
printf("Found %d cameras\n", config->count);
// Open the first camera
libmegapixels_camera *camera = config->cameras[camera_id];
libmegapixels_open(camera);
printf("Camera has %d modes\n", camera->num_modes);
// Select the first mode
libmegapixels_mode *mode = camera->modes[mode_idx];
struct v4l2_format format = {0};
libmegapixels_select_mode(camera, mode, &format);
// Now you can do regular V4L2 things on the camera with the
// supplied FDs. video_fd for the /dev/video device.
ioctl(camera->video_fd, VIDIOC_QUERYCAP, &cap)
Libmegapixels replaces most of the original V4L2 setup code and provides a
filled in :code:`struct v4l2_format` to get all the exact mode information.
To pick a camera and mode you'd iterate over the found cameras and then over
the mode structs to find something that matches the needs of the application.
The camera struct provides the FDs for the various devices you might need:
- The :code:`video_fd` field has the FD for :code:`/dev/video*` for actually
getting the frames.
- The :code:`sensor_fd` field is for the :code:`/dev/v4l-subdev*` device that
represents the sensor. This is for setting camera V4L2 controls while capturing.
- The :code:`media_fd` field is for the :code:`/dev/media*` device that has the
pipeline for the current camera. This is mostly for the libmegapixels internals.
The config files
----------------
The libmegapixels library ships with configuration files for some devices. The
device configuration can be stored in multiple locations so it can be overridden
by packagers and end users.
/usr/share/megapixels/config/%model.conf
This is the location where the config files from packages are stored. This is
also where the build script from libmegapixels will place the internal config
files here.
/etc/megapixels/config/%model.conf
This is the place for extra and/or override config files
$cwd/config/%model.conf
The config is loaded from the current working directory to make testing and
debugging the code easier and to run it from the root of the git repository.
The %model argument in the path is referring to the device-tree compatible names
of the device. This can be found in :code:`/proc/device-tree/compatible`. This
stores the name of the hardware seperated by null-bytes in decreasing specificity
order. Libmegapixels will check all of them in order for every location above.