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

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

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).

  1. void copy_plane_to_texture(const libcamera::FrameBuffer::Plane &plane, int w, int h, GLuint texture)
  2. {
  3. glBindTexture(GL_TEXTURE_2D, texture);
  4. auto *addr = (unsigned char *)mmap(nullptr, plane.length, PROT_READ, MAP_PRIVATE, plane.fd.get(), plane.offset);
  5. if (addr == MAP_FAILED)
  6. {
  7. clog << "mmap failed for plane fd " << plane.fd.get() << " size " << plane.length << " offset " << plane.offset << ": " << strerror(errno) << endl;
  8. abort();
  9. }
  10. clog << "plane fd " << plane.fd.get() << " size " << plane.length << " offset " << plane.offset << " mapped to address " << std::hex << size_t(addr) << std::dec << endl;
  11. glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, addr);
  12. glFinish(); // wait until copying is really finished
  13. if (munmap(addr, plane.length) != 0)
  14. {
  15. clog << "munmap failed on address " << std::hex << size_t(addr) << ": " << strerror(errno) << endl;
  16. abort();
  17. }
  18. }

A typical output log of this part:

  1. plane fd 18 size 921600 offset 0 mapped to address 6b51e000
  2. plane fd 18 size 230400 offset 921600 mapped to address 6b5c6000
  3. 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).

  1. void copy_plane_to_texture(const libcamera::FrameBuffer::Plane &amp;plane, int w, int h, GLuint texture)
  2. {
  3. glBindTexture(GL_TEXTURE_2D, texture);
  4. auto *addr = (unsigned char *)mmap(nullptr, plane.length, PROT_READ, MAP_PRIVATE, plane.fd.get(), plane.offset);
  5. if (addr == MAP_FAILED)
  6. {
  7. 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;
  8. abort();
  9. }
  10. 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;
  11. glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, addr);
  12. glFinish(); // wait until copying is really finished
  13. if (munmap(addr, plane.length) != 0)
  14. {
  15. 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;
  16. abort();
  17. }
  18. }

A typical output log of this part:

  1. plane fd 18 size 921600 offset 0 mapped to address 6b51e000
  2. plane fd 18 size 230400 offset 921600 mapped to address 6b5c6000
  3. 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:

确定