I'm working with camera on a Raspberry Pi 3B. The frame data returned by libcamera
is given by tuples of raw fd, size and offset. And according to the official document I have to mmap
them to access frame data. However, sometimes the code piece below fail to execute mmap
(usually occurs after one or two times of successful operations).
void copy_plane_to_texture(const libcamera::FrameBuffer::Plane &plane, int w, int h, GLuint texture)
{
glBindTexture(GL_TEXTURE_2D, texture);
auto *addr = (unsigned char *)mmap(nullptr, plane.length, PROT_READ, MAP_PRIVATE, plane.fd.get(), plane.offset);
if (addr == MAP_FAILED)
{
clog << "mmap failed for plane fd " << plane.fd.get() << " size " << plane.length << " offset " << plane.offset << ": " << strerror(errno) << endl;
abort();
}
clog << "plane fd " << plane.fd.get() << " size " << plane.length << " offset " << plane.offset << " mapped to address " << std::hex << size_t(addr) << std::dec << endl;
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, addr);
glFinish(); // wait until copying is really finished
if (munmap(addr, plane.length) != 0)
{
clog << "munmap failed on address " << std::hex << size_t(addr) << ": " << strerror(errno) << endl;
abort();
}
}
A typical output log of this part:
plane fd 18 size 921600 offset 0 mapped to address 6b51e000
plane fd 18 size 230400 offset 921600 mapped to address 6b5c6000
mmap failed for plane fd 18 size 230400 offset 1152000: Invalid argument
According to man 2 mmap
, it only raise EINVAL
on three circumstances:
- We don't like addr, length, or offset (e.g., they are too large, or not aligned on a page boundary).
- (since Linux 2.6.12) length was 0.
- flags contained neither MAP_PRIVATE or MAP_SHARED, or contained both of these values.
It is obvious I have non-zero length and has specified correct flag, so the remaining possibility is invalid length/offset. However the length/offset is given by libcamera
so I have no choice on it. How could I solve this error?
Somebody on another forum answered me. The color planes in one frame buffer is using the same dma file descriptor, and I should mmap
them in one time instead of three. Otherwise the offsets of latter planes are not aligned to page boundaries and mmap
will not happy.