From patchwork Sun Feb 3 11:00:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 493 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2D24C60B1B for ; Sun, 3 Feb 2019 12:01:08 +0100 (CET) Received: from localhost.localdomain (218.182-78-194.adsl-static.isp.belgacom.be [194.78.182.218]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id CADFB41; Sun, 3 Feb 2019 12:01:07 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1549191667; bh=0fw5UjSZFZh+JNXV5ehFKNSCl3dpJv03wlB0ejGnFxw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=d4JlOo9nWB+zXVff09eLt7wMSA3D7HqN2nwHd4WcCPLNXCd5OsnQF7KxuxgCgQMa8 bOGOUUKKOWkaaKJ5hQTdfeAAH4GpL+y8wi4qJnrDvcfItzQETKc4+JTotUdbuihAgi r0Ul37tvl+m+MBPwAHp8ZcppX9PEsnlUEqEvtafM= From: Kieran Bingham To: LibCamera Devel Date: Sun, 3 Feb 2019 12:00:57 +0100 Message-Id: <20190203110102.5663-7-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> References: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 06/11] libcamera: v4l2_device: Implement stream{On, Off} X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 03 Feb 2019 11:01:08 -0000 Support starting and stopping a stream on a V4L2 device. This requires having buffers queued, thus both queueBuffer() and dequeueBuffer() are also added. Signed-off-by: Kieran Bingham --- src/libcamera/include/v4l2_device.h | 6 ++ src/libcamera/v4l2_device.cpp | 134 ++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h index f445f98f97a4..d3dad355be58 100644 --- a/src/libcamera/include/v4l2_device.h +++ b/src/libcamera/include/v4l2_device.h @@ -101,6 +101,12 @@ public: BufferPool *requestBuffers(unsigned int qty = 8); + int queueBuffer(Buffer *frame); + Buffer *dequeueBuffer(); + + int streamOn(); + int streamOff(); + private: int getFormatSingleplane(V4L2DeviceFormat *fmt); int setFormatSingleplane(V4L2DeviceFormat *fmt); diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 728478a1ae8f..1fd289137b36 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -592,4 +592,138 @@ int V4L2Device::setFormatMultiplane(V4L2DeviceFormat *fmt) return 0; } +/** + * \brief Queue a buffer into the device. + * + * For Capture devices the buffer will be operated on and can be dequeued later + * with active data. + * + * For Output devices the buffer should contain valid data and will be processed + * by the receiving device. The buffer will be available to dequeue when it is + * no longer in use by the Output device. + * + * \return 0 if the operation completes or a negative error number otherwise + */ +int V4L2Device::queueBuffer(Buffer *frame) +{ + struct v4l2_buffer buf = {}; + struct v4l2_plane planes[VIDEO_MAX_PLANES] = {}; + int ret; + + buf.index = frame->index(); + buf.type = bufferType_; + buf.memory = memoryType_; + + if (V4L2_TYPE_IS_MULTIPLANAR(buf.type)) { + buf.length = frame->planes().size(); + buf.m.planes = planes; + } + + LOG(V4L2, Debug) << "Queueing buffer idx: " << buf.index; + + ret = ioctl(fd_, VIDIOC_QBUF, &buf); + if (ret < 0) { + ret = -errno; + LOG(V4L2, Error) + << "Failed to queue buffer: " << strerror(-ret); + return ret; + } + + return 0; +} + +/** + * \brief dequeue a buffer from the device + * + * For Capture devices the buffer will be contain valid data and can be used for + * further processing. The buffer should be re-queued when it is no longer in + * use. + * + * For Output devices the buffer has been processed by the hardware and can now + * be freely re-used. + * + * \return A Buffer pointer if the operation completes or a nullptr otherwise + */ +Buffer *V4L2Device::dequeueBuffer() +{ + struct v4l2_buffer buf = {}; + struct v4l2_plane planes[VIDEO_MAX_PLANES] = {}; + int ret; + + buf.type = bufferType_; + buf.memory = memoryType_; + + if (V4L2_TYPE_IS_MULTIPLANAR(buf.type)) { + buf.length = VIDEO_MAX_PLANES; + buf.m.planes = planes; + } + + ret = ioctl(fd_, VIDIOC_DQBUF, &buf); + if (ret < 0) { + ret = -errno; + LOG(V4L2, Error) + << "Failed to dequeue buffer: " << strerror(-ret); + return nullptr; + } + + if (buf.index >= bufferPool_->buffers().size()) { + LOG(V4L2, Error) << "Invalid buffer index dequeued"; + return nullptr; + } + + return bufferPool_->buffers()[buf.index]; +} + +/** + * \brief Request that the V4L2Device commences streaming + * + * Prepares the device to start processing Buffers, and connects the completion + * handler to the bufferAvailable Slot. + * + * \return 0 if the operation completes or a negative error number otherwise + */ +int V4L2Device::streamOn() +{ + int ret; + + if (caps_.isCapture()) { + for (Buffer *b : bufferPool_->buffers()) { + ret = queueBuffer(b); + if (ret) + return ret; + } + } + + ret = ioctl(fd_, VIDIOC_STREAMON, &bufferType_); + if (ret < 0) { + ret = -errno; + LOG(V4L2, Error) + << "Failed to start streaming: " << strerror(-ret); + return ret; + } + + return 0; +} + +/** + * \brief Request that the V4L2Device stops streaming + * + * Asks the device to halt any current streaming operations. + * + * \return 0 if the operation completes or a negative error number otherwise + */ +int V4L2Device::streamOff() +{ + int ret; + + ret = ioctl(fd_, VIDIOC_STREAMOFF, &bufferType_); + if (ret < 0) { + LOG(V4L2, Error) + << "Failed to stop streaming: " << strerror(errno); + return ret; + } + + return 0; +} + } /* namespace libcamera */