summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJacopo Mondi <jacopo@jmondi.org>2020-01-07 17:38:21 +0100
committerJacopo Mondi <jacopo@jmondi.org>2020-01-08 10:53:58 +0100
commit769ca0a5503ce99fd9687aa3a3a96eea6242116c (patch)
tree8ed6fc79ecbe2194b15a6ebcf82f2238689d3288 /src
parenteccbb175516670f13c6a4f8f9e4ed8bc1228938c (diff)
v4l2: camera_proxy: Fix try_fmt format conversion
The set pixelformat field of struct v4l2_pix_format structure was wrongly converted to PixelFormat by calling v4l2ToDrm(), with an already converted 'format' argument. Fix this by calling the right drmToV4l2() conversion function. Fixes: 0ce8f2390b52 ("v4l2: v4l2_compat: Add V4L2 compatibility layer") Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Diffstat (limited to 'src')
-rw-r--r--src/v4l2/v4l2_camera_proxy.cpp2
1 files changed, 1 insertions, 1 deletions
diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp
index 8d1b40da..0f1d5ea4 100644
--- a/src/v4l2/v4l2_camera_proxy.cpp
+++ b/src/v4l2/v4l2_camera_proxy.cpp
@@ -282,7 +282,7 @@ int V4L2CameraProxy::vidioc_try_fmt(struct v4l2_format *arg)
arg->fmt.pix.width = size.width;
arg->fmt.pix.height = size.height;
- arg->fmt.pix.pixelformat = v4l2ToDrm(format);
+ arg->fmt.pix.pixelformat = drmToV4L2(format);
arg->fmt.pix.field = V4L2_FIELD_NONE;
arg->fmt.pix.bytesperline = bplMultiplier(drmToV4L2(format)) *
arg->fmt.pix.width;
2' href='#n212'>212 213 214 215 216 217 218 219 220 221 222 223 224
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2019, Google Inc.
 *
 * v4l2_camera.cpp - V4L2 compatibility camera
 */

#include "v4l2_camera.h"

#include <errno.h>
#include <unistd.h>

#include "libcamera/internal/log.h"

using namespace libcamera;

LOG_DECLARE_CATEGORY(V4L2Compat);

V4L2Camera::V4L2Camera(std::shared_ptr<Camera> camera)
	: camera_(camera), isRunning_(false), bufferAllocator_(nullptr)
{
	camera_->requestCompleted.connect(this, &V4L2Camera::requestComplete);
}

V4L2Camera::~V4L2Camera()
{
	close();
}

int V4L2Camera::open()
{
	/* \todo Support multiple open. */
	if (camera_->acquire() < 0) {
		LOG(V4L2Compat, Error) << "Failed to acquire camera";
		return -EINVAL;
	}

	config_ = camera_->generateConfiguration({ StreamRole::Viewfinder });
	if (!config_) {
		camera_->release();
		return -EINVAL;
	}

	bufferAllocator_ = new FrameBufferAllocator(camera_);

	return 0;
}

void V4L2Camera::close()
{
	delete bufferAllocator_;
	bufferAllocator_ = nullptr;

	camera_->release();
}

void V4L2Camera::bind(int efd)
{
	efd_ = efd;
}

void V4L2Camera::getStreamConfig(StreamConfiguration *streamConfig)
{
	*streamConfig = config_->at(0);
}

std::vector<V4L2Camera::Buffer> V4L2Camera::completedBuffers()
{
	std::vector<Buffer> v;

	bufferLock_.lock();
	for (std::unique_ptr<Buffer> &metadata : completedBuffers_)
		v.push_back(*metadata.get());
	completedBuffers_.clear();
	bufferLock_.unlock();

	return v;
}

void V4L2Camera::requestComplete(Request *request)
{
	if (request->status() == Request::RequestCancelled)
		return;

	/* We only have one stream at the moment. */
	bufferLock_.lock();
	FrameBuffer *buffer = request->buffers().begin()->second;
	std::unique_ptr<Buffer> metadata =
		std::make_unique<Buffer>(request->cookie(), buffer->metadata());
	completedBuffers_.push_back(std::move(metadata));
	bufferLock_.unlock();

	uint64_t data = 1;
	int ret = ::write(efd_, &data, sizeof(data));
	if (ret != sizeof(data))
		LOG(V4L2Compat, Error) << "Failed to signal eventfd POLLIN";

	bufferSema_.release();
}

int V4L2Camera::configure(StreamConfiguration *streamConfigOut,
			  const Size &size, const PixelFormat &pixelformat,
			  unsigned int bufferCount)
{
	StreamConfiguration &streamConfig = config_->at(0);
	streamConfig.size.width = size.width;
	streamConfig.size.height = size.height;
	streamConfig.pixelFormat = pixelformat;
	streamConfig.bufferCount = bufferCount;
	/* \todo memoryType (interval vs external) */

	CameraConfiguration::Status validation = config_->validate();
	if (validation == CameraConfiguration::Invalid) {
		LOG(V4L2Compat, Debug) << "Configuration invalid";
		return -EINVAL;
	}
	if (validation == CameraConfiguration::Adjusted)
		LOG(V4L2Compat, Debug) << "Configuration adjusted";

	LOG(V4L2Compat, Debug) << "Validated configuration is: "
			      << streamConfig.toString();

	int ret = camera_->configure(config_.get());
	if (ret < 0)
		return ret;

	*streamConfigOut = config_->at(0);

	return 0;
}

int V4L2Camera::allocBuffers(unsigned int count)
{
	Stream *stream = *camera_->streams().begin();

	return bufferAllocator_->allocate(stream);
}

void V4L2Camera::freeBuffers()
{
	Stream *stream = *camera_->streams().begin();
	bufferAllocator_->free(stream);
}

FileDescriptor V4L2Camera::getBufferFd(unsigned int index)
{
	Stream *stream = *camera_->streams().begin();
	const std::vector<std::unique_ptr<FrameBuffer>> &buffers =
		bufferAllocator_->buffers(stream);

	if (buffers.size() <= index)
		return FileDescriptor();

	return buffers[index]->planes()[0].fd;
}

int V4L2Camera::streamOn()
{
	if (isRunning_)
		return 0;

	int ret = camera_->start();
	if (ret < 0)
		return ret == -EACCES ? -EBUSY : ret;

	isRunning_ = true;

	for (std::unique_ptr<Request> &req : pendingRequests_) {
		/* \todo What should we do if this returns -EINVAL? */
		ret = camera_->queueRequest(req.release());
		if (ret < 0)
			return ret == -EACCES ? -EBUSY : ret;
	}

	pendingRequests_.clear();

	return 0;
}

int V4L2Camera::streamOff()
{
	/* \todo Restore buffers to reqbufs state? */
	if (!isRunning_)
		return 0;

	int ret = camera_->stop();
	if (ret < 0)
		return ret == -EACCES ? -EBUSY : ret;

	isRunning_ = false;

	return 0;
}

int V4L2Camera::qbuf(unsigned int index)
{
	std::unique_ptr<Request> request =
		std::unique_ptr<Request>(camera_->createRequest(index));
	if (!request) {
		LOG(V4L2Compat, Error) << "Can't create request";
		return -ENOMEM;
	}

	Stream *stream = config_->at(0).stream();
	FrameBuffer *buffer = bufferAllocator_->buffers(stream)[index].get();
	int ret = request->addBuffer(stream, buffer);
	if (ret < 0) {
		LOG(V4L2Compat, Error) << "Can't set buffer for request";
		return -ENOMEM;
	}

	if (!isRunning_) {
		pendingRequests_.push_back(std::move(request));
		return 0;
	}

	ret = camera_->queueRequest(request.release());
	if (ret < 0) {
		LOG(V4L2Compat, Error) << "Can't queue request";
		return ret == -EACCES ? -EBUSY : ret;
	}

	return 0;
}