@@ -141,7 +141,7 @@ LOG_DECLARE_CATEGORY(V4L2)
* \brief Hot cache of associations between V4L2 buffer indexes and FrameBuffer
*
* When importing buffers, V4L2 performs lazy mapping of dmabuf instances at
- * VIDIOC_QBUF (or VIDIOC_PREPARE_BUF) time and keeps the mapping associated
+ * VIDIOC_EXT_QBUF (or VIDIOC_PREPARE_BUF) time and keeps the mapping associated
* with the V4L2 buffer, as identified by its index. If the same V4L2 buffer is
* then reused and queued with different dmabufs, the old dmabufs will be
* unmapped and the new ones mapped. To keep this process efficient, it is
@@ -1315,8 +1315,8 @@ int V4L2VideoDevice::releaseBuffers()
*/
int V4L2VideoDevice::queueBuffer(FrameBuffer *buffer)
{
- struct v4l2_plane v4l2Planes[VIDEO_MAX_PLANES] = {};
- struct v4l2_buffer buf = {};
+ V4L2DeviceFormat format;
+ struct v4l2_ext_buffer buf = {};
int ret;
ret = cache_->get(*buffer);
@@ -1328,46 +1328,46 @@ int V4L2VideoDevice::queueBuffer(FrameBuffer *buffer)
buf.memory = memoryType_;
buf.field = V4L2_FIELD_NONE;
- bool multiPlanar = V4L2_TYPE_IS_MULTIPLANAR(buf.type);
const std::vector<FrameBuffer::Plane> &planes = buffer->planes();
+ ret = getFormat(&format);
+ if (ret < 0)
+ return ret;
+
if (buf.memory == V4L2_MEMORY_DMABUF) {
- if (multiPlanar) {
- for (unsigned int p = 0; p < planes.size(); ++p)
- v4l2Planes[p].m.fd = planes[p].fd.fd();
+ /*
+ * If there is a single memory plane, fill color planes with
+ * the same dmabuf fd but on a different offset
+ */
+ if (planes.size() == 1) {
+ buf.planes[0].m.dmabuf_fd = planes[0].fd.fd();
+ for (unsigned int p = 1;
+ p < format.planes.size() && format.planes[p].size; ++p) {
+ buf.planes[p].m.dmabuf_fd = planes[0].fd.fd();
+ buf.planes[p].offset = format.planes[p - 1].size;
+ }
} else {
- buf.m.fd = planes[0].fd.fd();
+ for (unsigned int p = 0; p < planes.size(); ++p)
+ buf.planes[p].m.dmabuf_fd = planes[p].fd.fd();
}
}
- if (multiPlanar) {
- buf.length = planes.size();
- buf.m.planes = v4l2Planes;
- }
-
if (V4L2_TYPE_IS_OUTPUT(buf.type)) {
const FrameMetadata &metadata = buffer->metadata();
+ unsigned int nplane = 0;
- if (multiPlanar) {
- unsigned int nplane = 0;
- for (const FrameMetadata::Plane &plane : metadata.planes) {
- v4l2Planes[nplane].bytesused = plane.bytesused;
- v4l2Planes[nplane].length = buffer->planes()[nplane].length;
- nplane++;
- }
- } else {
- if (metadata.planes.size())
- buf.bytesused = metadata.planes[0].bytesused;
+ for (const FrameMetadata::Plane &plane : metadata.planes) {
+ buf.planes[nplane].bytesused = plane.bytesused;
+ nplane++;
}
buf.sequence = metadata.sequence;
- buf.timestamp.tv_sec = metadata.timestamp / 1000000000;
- buf.timestamp.tv_usec = (metadata.timestamp / 1000) % 1000000;
+ buf.timestamp = metadata.timestamp;
}
LOG(V4L2, Debug) << "Queueing buffer " << buf.index;
- ret = ioctl(VIDIOC_QBUF, &buf);
+ ret = ioctl(VIDIOC_EXT_QBUF, &buf);
if (ret < 0) {
LOG(V4L2, Error)
<< "Failed to queue buffer " << buf.index << ": "
@@ -1413,21 +1413,13 @@ void V4L2VideoDevice::bufferAvailable([[maybe_unused]] EventNotifier *notifier)
*/
FrameBuffer *V4L2VideoDevice::dequeueBuffer()
{
- struct v4l2_buffer buf = {};
- struct v4l2_plane planes[VIDEO_MAX_PLANES] = {};
+ struct v4l2_ext_buffer buf = {};
int ret;
buf.type = bufferType_;
buf.memory = memoryType_;
- bool multiPlanar = V4L2_TYPE_IS_MULTIPLANAR(buf.type);
-
- if (multiPlanar) {
- buf.length = VIDEO_MAX_PLANES;
- buf.m.planes = planes;
- }
-
- ret = ioctl(VIDIOC_DQBUF, &buf);
+ ret = ioctl(VIDIOC_EXT_DQBUF, &buf);
if (ret < 0) {
LOG(V4L2, Error)
<< "Failed to dequeue buffer: " << strerror(-ret);
@@ -1449,16 +1441,11 @@ FrameBuffer *V4L2VideoDevice::dequeueBuffer()
? FrameMetadata::FrameError
: FrameMetadata::FrameSuccess;
buffer->metadata_.sequence = buf.sequence;
- buffer->metadata_.timestamp = buf.timestamp.tv_sec * 1000000000ULL
- + buf.timestamp.tv_usec * 1000ULL;
+ buffer->metadata_.timestamp = buf.timestamp;
buffer->metadata_.planes.clear();
- if (multiPlanar) {
- for (unsigned int nplane = 0; nplane < buf.length; nplane++)
- buffer->metadata_.planes.push_back({ planes[nplane].bytesused });
- } else {
- buffer->metadata_.planes.push_back({ buf.bytesused });
- }
+ for (unsigned int nplane = 0; buf.planes[nplane].bytesused; nplane++)
+ buffer->metadata_.planes.push_back({ buf.planes[nplane].bytesused });
return buffer;
}
@@ -544,9 +544,9 @@ int V4L2CameraProxy::vidioc_querybuf(V4L2CameraFile *file, struct v4l2_buffer *a
return 0;
}
-int V4L2CameraProxy::vidioc_qbuf(V4L2CameraFile *file, struct v4l2_buffer *arg)
+int V4L2CameraProxy::vidioc_ext_qbuf(V4L2CameraFile *file, struct v4l2_ext_buffer *arg)
{
- LOG(V4L2Compat, Debug) << "Servicing vidioc_qbuf, index = "
+ LOG(V4L2Compat, Debug) << "Servicing vidioc_ext_qbuf, index = "
<< arg->index << " fd = " << file->efd();
if (arg->index >= bufferCount_)
@@ -574,8 +574,8 @@ int V4L2CameraProxy::vidioc_qbuf(V4L2CameraFile *file, struct v4l2_buffer *arg)
return ret;
}
-int V4L2CameraProxy::vidioc_dqbuf(V4L2CameraFile *file, struct v4l2_buffer *arg,
- MutexLocker *locker)
+int V4L2CameraProxy::vidioc_ext_dqbuf(V4L2CameraFile *file, struct v4l2_ext_buffer *arg,
+ MutexLocker *locker)
{
LOG(V4L2Compat, Debug) << "Servicing vidioc_dqbuf fd = " << file->efd();
@@ -683,8 +683,8 @@ const std::set<unsigned long> V4L2CameraProxy::supportedIoctls_ = {
VIDIOC_S_INPUT,
VIDIOC_REQBUFS,
VIDIOC_QUERYBUF,
- VIDIOC_QBUF,
- VIDIOC_DQBUF,
+ VIDIOC_EXT_QBUF,
+ VIDIOC_EXT_DQBUF,
VIDIOC_STREAMON,
VIDIOC_STREAMOFF,
};
@@ -749,11 +749,11 @@ int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *ar
case VIDIOC_QUERYBUF:
ret = vidioc_querybuf(file, static_cast<struct v4l2_buffer *>(arg));
break;
- case VIDIOC_QBUF:
- ret = vidioc_qbuf(file, static_cast<struct v4l2_buffer *>(arg));
+ case VIDIOC_EXT_QBUF:
+ ret = vidioc_ext_qbuf(file, static_cast<struct v4l2_ext_buffer *>(arg));
break;
- case VIDIOC_DQBUF:
- ret = vidioc_dqbuf(file, static_cast<struct v4l2_buffer *>(arg), &locker);
+ case VIDIOC_EXT_DQBUF:
+ ret = vidioc_ext_dqbuf(file, static_cast<struct v4l2_ext_buffer *>(arg), &locker);
break;
case VIDIOC_STREAMON:
ret = vidioc_streamon(file, static_cast<int *>(arg));
Use Ext API for buffer handling. Allow memory buffers to be defined per color component. Signed-off-by: Helen Koike <helen.koike@collabora.com> --- src/libcamera/v4l2_videodevice.cpp | 75 ++++++++++++------------------ src/v4l2/v4l2_camera_proxy.cpp | 20 ++++---- 2 files changed, 41 insertions(+), 54 deletions(-)