mmap 在 libcamera 上失败,返回帧数据

huangapple go评论76阅读模式
英文:

mmap failed on libcamera returned frame data

问题

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?

英文:

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 &amp;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 &lt;&lt; &quot;mmap failed for plane fd &quot; &lt;&lt; plane.fd.get() &lt;&lt; &quot; size &quot; &lt;&lt; plane.length &lt;&lt; &quot; offset &quot; &lt;&lt; plane.offset &lt;&lt; &quot;: &quot; &lt;&lt; strerror(errno) &lt;&lt; endl;
        abort();
    }
    clog &lt;&lt; &quot;plane fd &quot; &lt;&lt; plane.fd.get() &lt;&lt; &quot; size &quot; &lt;&lt; plane.length &lt;&lt; &quot; offset &quot; &lt;&lt; plane.offset &lt;&lt; &quot; mapped to address &quot; &lt;&lt; std::hex &lt;&lt; size_t(addr) &lt;&lt; std::dec &lt;&lt; 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 &lt;&lt; &quot;munmap failed on address &quot; &lt;&lt; std::hex &lt;&lt; size_t(addr) &lt;&lt; &quot;: &quot; &lt;&lt; strerror(errno) &lt;&lt; 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?

答案1

得分: 0

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.

英文:

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.

huangapple
  • 本文由 发表于 2023年5月17日 17:52:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76270783.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定