v4l2: camera: Handle memory mapping of buffers directly

In the upcoming FrameBuffer API the memory mapping of buffers will be
left to the user of the FrameBuffer objects. Prepare the V4L2
compatibility layer to this upcoming change to ease conversion to the
new API.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
Niklas Söderlund 2020-01-09 15:20:44 +01:00
parent 35ac23dca1
commit 3c4b872443
5 changed files with 30 additions and 15 deletions

View file

@ -121,12 +121,6 @@ int V4L2Camera::configure(StreamConfiguration *streamConfigOut,
return 0; return 0;
} }
void *V4L2Camera::mmap(unsigned int index)
{
Stream *stream = *camera_->streams().begin();
return stream->buffers()[index].planes()[0].mem();
}
int V4L2Camera::allocBuffers(unsigned int count) int V4L2Camera::allocBuffers(unsigned int count)
{ {
int ret = camera_->allocateBuffers(); int ret = camera_->allocateBuffers();
@ -138,6 +132,12 @@ void V4L2Camera::freeBuffers()
camera_->freeBuffers(); camera_->freeBuffers();
} }
FileDescriptor V4L2Camera::getBufferFd(unsigned int index)
{
Stream *stream = *camera_->streams().begin();
return FileDescriptor(stream->buffers()[index].planes()[0].dmabuf());
}
int V4L2Camera::streamOn() int V4L2Camera::streamOn()
{ {
if (isRunning_) if (isRunning_)

View file

@ -14,6 +14,7 @@
#include <libcamera/buffer.h> #include <libcamera/buffer.h>
#include <libcamera/camera.h> #include <libcamera/camera.h>
#include <libcamera/file_descriptor.h>
#include "semaphore.h" #include "semaphore.h"
@ -53,14 +54,14 @@ public:
void getStreamConfig(StreamConfiguration *streamConfig); void getStreamConfig(StreamConfiguration *streamConfig);
std::vector<V4L2FrameMetadata> completedBuffers(); std::vector<V4L2FrameMetadata> completedBuffers();
void *mmap(unsigned int index);
int configure(StreamConfiguration *streamConfigOut, int configure(StreamConfiguration *streamConfigOut,
const Size &size, PixelFormat pixelformat, const Size &size, PixelFormat pixelformat,
unsigned int bufferCount); unsigned int bufferCount);
int allocBuffers(unsigned int count); int allocBuffers(unsigned int count);
void freeBuffers(); void freeBuffers();
FileDescriptor getBufferFd(unsigned int index);
int streamOn(); int streamOn();
int streamOff(); int streamOff();

View file

@ -75,7 +75,8 @@ void V4L2CameraProxy::close()
vcam_->invokeMethod(&V4L2Camera::close, ConnectionTypeBlocking); vcam_->invokeMethod(&V4L2Camera::close, ConnectionTypeBlocking);
} }
void *V4L2CameraProxy::mmap(size_t length, int prot, int flags, off_t offset) void *V4L2CameraProxy::mmap(void *addr, size_t length, int prot, int flags,
off_t offset)
{ {
LOG(V4L2Compat, Debug) << "Servicing mmap"; LOG(V4L2Compat, Debug) << "Servicing mmap";
@ -91,13 +92,22 @@ void *V4L2CameraProxy::mmap(size_t length, int prot, int flags, off_t offset)
return MAP_FAILED; return MAP_FAILED;
} }
void *val = vcam_->invokeMethod(&V4L2Camera::mmap, FileDescriptor fd = vcam_->invokeMethod(&V4L2Camera::getBufferFd,
ConnectionTypeBlocking, index); ConnectionTypeBlocking, index);
if (!fd.isValid()) {
errno = EINVAL;
return MAP_FAILED;
}
void *map = V4L2CompatManager::instance()->fops().mmap(addr, length, prot,
flags, fd.fd(), 0);
if (map == MAP_FAILED)
return map;
buffers_[index].flags |= V4L2_BUF_FLAG_MAPPED; buffers_[index].flags |= V4L2_BUF_FLAG_MAPPED;
mmaps_[val] = index; mmaps_[map] = index;
return val; return map;
} }
int V4L2CameraProxy::munmap(void *addr, size_t length) int V4L2CameraProxy::munmap(void *addr, size_t length)
@ -110,6 +120,10 @@ int V4L2CameraProxy::munmap(void *addr, size_t length)
return -1; return -1;
} }
if (V4L2CompatManager::instance()->fops().munmap(addr, length))
LOG(V4L2Compat, Error) << "Failed to unmap " << addr
<< " with length " << length;
buffers_[iter->second].flags &= ~V4L2_BUF_FLAG_MAPPED; buffers_[iter->second].flags &= ~V4L2_BUF_FLAG_MAPPED;
mmaps_.erase(iter); mmaps_.erase(iter);

View file

@ -28,7 +28,7 @@ public:
int open(bool nonBlocking); int open(bool nonBlocking);
void dup(); void dup();
void close(); void close();
void *mmap(size_t length, int prot, int flags, off_t offset); void *mmap(void *addr, size_t length, int prot, int flags, off_t offset);
int munmap(void *addr, size_t length); int munmap(void *addr, size_t length);
int ioctl(unsigned long request, void *arg); int ioctl(unsigned long request, void *arg);

View file

@ -223,7 +223,7 @@ void *V4L2CompatManager::mmap(void *addr, size_t length, int prot, int flags,
if (!proxy) if (!proxy)
return fops_.mmap(addr, length, prot, flags, fd, offset); return fops_.mmap(addr, length, prot, flags, fd, offset);
void *map = proxy->mmap(length, prot, flags, offset); void *map = proxy->mmap(addr, length, prot, flags, offset);
if (map == MAP_FAILED) if (map == MAP_FAILED)
return map; return map;