8#include <private/qcameradevice_p.h>
9#include <private/qmultimediautils_p.h>
10#include <private/qmemoryvideobuffer_p.h>
11#include <private/qcore_unix_p.h>
49 while (
f->v4l2Format) {
60 while (
f->v4l2Format) {
86 if (m_active == active)
88 if (m_cameraDevice.
isNull() && active)
107 if (m_cameraDevice ==
camera)
166 setV4L2Parameter(V4L2_CID_FOCUS_AUTO, 1);
168 setV4L2Parameter(V4L2_CID_AUTO_FOCUS_RANGE, V4L2_AUTO_FOCUS_RANGE_AUTO);
171 setV4L2Parameter(V4L2_CID_FOCUS_AUTO, 1);
173 setV4L2Parameter(V4L2_CID_AUTO_FOCUS_RANGE, V4L2_AUTO_FOCUS_RANGE_MACRO);
175 setV4L2Parameter(V4L2_CID_FOCUS_ABSOLUTE, m_v4l2Info.
minFocus);
178 setV4L2Parameter(V4L2_CID_FOCUS_AUTO, 1);
180 setV4L2Parameter(V4L2_CID_AUTO_FOCUS_RANGE, V4L2_AUTO_FOCUS_RANGE_INFINITY);
183 setV4L2Parameter(V4L2_CID_FOCUS_AUTO, 0);
184 setV4L2Parameter(V4L2_CID_FOCUS_ABSOLUTE, m_v4l2Info.
maxFocus);
187 setV4L2Parameter(V4L2_CID_FOCUS_AUTO, 0);
197 setV4L2Parameter(V4L2_CID_FOCUS_ABSOLUTE,
distance);
205 factor =
qBound(1., factor, 2.);
207 setV4L2Parameter(V4L2_CID_ZOOM_ABSOLUTE, zoom);
224 setV4L2Parameter(V4L2_CID_FLASH_LED_MODE,
mode ==
QCamera::FlashAuto ? V4L2_FLASH_LED_MODE_FLASH : V4L2_FLASH_LED_MODE_NONE);
237 struct v4l2_queryctrl queryControl;
238 ::memset(&queryControl, 0,
sizeof(queryControl));
239 queryControl.id = V4L2_CID_AUTO_WHITE_BALANCE;
241 return m_v4l2FileDescriptor && m_v4l2FileDescriptor->call(VIDIOC_QUERYCTRL, &queryControl);
248 setV4L2Parameter(V4L2_CID_FLASH_LED_MODE,
mode ==
QCamera::TorchOn ? V4L2_FLASH_LED_MODE_TORCH : V4L2_FLASH_LED_MODE_NONE);
265 setV4L2Parameter(V4L2_CID_EXPOSURE_AUTO,
value);
285 setV4L2Parameter(V4L2_CID_AUTO_EXPOSURE_BIAS,
value);
295 setV4L2Parameter(V4L2_CID_ISO_SENSITIVITY_AUTO, iso <= 0 ? V4L2_ISO_SENSITIVITY_AUTO : V4L2_ISO_SENSITIVITY_MANUAL);
298 setV4L2Parameter(V4L2_CID_ISO_SENSITIVITY, iso);
307 return getV4L2Parameter(V4L2_CID_ISO_SENSITIVITY);
315 setV4L2Parameter(V4L2_CID_EXPOSURE_ABSOLUTE, exposure);
323 return getV4L2Parameter(V4L2_CID_EXPOSURE_ABSOLUTE)/10000.;
339 int t = setV4L2ColorTemperature(temperature);
347 if (temperature == 0) {
354 int t = setV4L2ColorTemperature(temperature);
359void QV4L2Camera::readFrame()
363 auto buffer = m_memoryTransfer->dequeueBuffer();
365 qCWarning(qLcV4L2Camera) <<
"Cannot take buffer";
367 if (errno == ENODEV) {
379 auto &v4l2Buffer =
buffer->v4l2Buffer;
381 if (m_firstFrameTime.tv_sec == -1)
382 m_firstFrameTime = v4l2Buffer.timestamp;
383 qint64 secs = v4l2Buffer.timestamp.tv_sec - m_firstFrameTime.tv_sec;
384 qint64 usecs = v4l2Buffer.timestamp.tv_usec - m_firstFrameTime.tv_usec;
385 frame.setStartTime(secs*1000000 + usecs);
386 frame.setEndTime(
frame.startTime() + m_frameDuration);
390 if (!m_memoryTransfer->enqueueBuffer(v4l2Buffer.index))
391 qCWarning(qLcV4L2Camera) <<
"Cannot add buffer";
394void QV4L2Camera::setCameraBusy()
400void QV4L2Camera::initV4L2Controls()
403 QCamera::Features features;
411 if (descriptor == -1) {
413 <<
"for read to query the parameter info:"
419 m_v4l2FileDescriptor = std::make_shared<QV4L2FileDescriptor>(descriptor);
421 qCDebug(qLcV4L2Camera) <<
"FD=" << descriptor;
423 struct v4l2_queryctrl queryControl;
424 ::memset(&queryControl, 0,
sizeof(queryControl));
425 queryControl.id = V4L2_CID_AUTO_WHITE_BALANCE;
427 if (m_v4l2FileDescriptor->call(VIDIOC_QUERYCTRL, &queryControl)) {
429 setV4L2Parameter(V4L2_CID_AUTO_WHITE_BALANCE,
true);
432 ::memset(&queryControl, 0,
sizeof(queryControl));
433 queryControl.id = V4L2_CID_WHITE_BALANCE_TEMPERATURE;
434 if (m_v4l2FileDescriptor->call(VIDIOC_QUERYCTRL, &queryControl)) {
441 ::memset(&queryControl, 0,
sizeof(queryControl));
442 queryControl.id = V4L2_CID_EXPOSURE_AUTO;
443 if (m_v4l2FileDescriptor->call(VIDIOC_QUERYCTRL, &queryControl)) {
447 ::memset(&queryControl, 0,
sizeof(queryControl));
448 queryControl.id = V4L2_CID_EXPOSURE_ABSOLUTE;
449 if (m_v4l2FileDescriptor->call(VIDIOC_QUERYCTRL, &queryControl)) {
456 ::memset(&queryControl, 0,
sizeof(queryControl));
457 queryControl.id = V4L2_CID_AUTO_EXPOSURE_BIAS;
458 if (m_v4l2FileDescriptor->call(VIDIOC_QUERYCTRL, &queryControl)) {
464 ::memset(&queryControl, 0,
sizeof(queryControl));
465 queryControl.id = V4L2_CID_ISO_SENSITIVITY_AUTO;
466 if (m_v4l2FileDescriptor->call(VIDIOC_QUERYCTRL, &queryControl)) {
467 queryControl.id = V4L2_CID_ISO_SENSITIVITY;
468 if (m_v4l2FileDescriptor->call(VIDIOC_QUERYCTRL, &queryControl)) {
475 ::memset(&queryControl, 0,
sizeof(queryControl));
476 queryControl.id = V4L2_CID_FOCUS_ABSOLUTE;
477 if (m_v4l2FileDescriptor->call(VIDIOC_QUERYCTRL, &queryControl)) {
483 ::memset(&queryControl, 0,
sizeof(queryControl));
484 queryControl.id = V4L2_CID_AUTO_FOCUS_RANGE;
485 if (m_v4l2FileDescriptor->call(VIDIOC_QUERYCTRL, &queryControl)) {
489 ::memset(&queryControl, 0,
sizeof(queryControl));
490 queryControl.id = V4L2_CID_FLASH_LED_MODE;
491 if (m_v4l2FileDescriptor->call(VIDIOC_QUERYCTRL, &queryControl)) {
492 m_v4l2Info.
flashSupported = queryControl.minimum <= V4L2_FLASH_LED_MODE_FLASH
493 && queryControl.maximum >= V4L2_FLASH_LED_MODE_FLASH;
494 m_v4l2Info.
torchSupported = queryControl.minimum <= V4L2_FLASH_LED_MODE_TORCH
495 && queryControl.maximum >= V4L2_FLASH_LED_MODE_TORCH;
498 ::memset(&queryControl, 0,
sizeof(queryControl));
499 queryControl.id = V4L2_CID_ZOOM_ABSOLUTE;
500 if (m_v4l2FileDescriptor->call(VIDIOC_QUERYCTRL, &queryControl)) {
501 m_v4l2Info.
minZoom = queryControl.minimum;
502 m_v4l2Info.
maxZoom = queryControl.maximum;
512void QV4L2Camera::closeV4L2Fd()
517 m_cameraBusy =
false;
518 m_v4l2FileDescriptor =
nullptr;
521int QV4L2Camera::setV4L2ColorTemperature(
int temperature)
523 struct v4l2_control control;
524 ::memset(&control, 0,
sizeof(control));
527 setV4L2Parameter(V4L2_CID_AUTO_WHITE_BALANCE, temperature == 0 ?
true :
false);
528 }
else if (temperature == 0) {
534 if (!setV4L2Parameter(
535 V4L2_CID_WHITE_BALANCE_TEMPERATURE,
547 v4l2_control control{
id,
value };
548 if (!m_v4l2FileDescriptor->call(VIDIOC_S_CTRL, &control)) {
555int QV4L2Camera::getV4L2Parameter(
quint32 id)
const
557 struct v4l2_control control{
id, 0};
558 if (!m_v4l2FileDescriptor->call(VIDIOC_G_CTRL, &control)) {
562 return control.value;
565void QV4L2Camera::setV4L2CameraFormat()
574 v4l2_format
fmt = {};
575 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
579 fmt.fmt.pix.height =
size.height();
581 fmt.fmt.pix.field = V4L2_FIELD_ANY;
583 qCDebug(qLcV4L2Camera) <<
"setting camera format to" <<
size <<
fmt.fmt.pix.pixelformat;
585 if (!m_v4l2FileDescriptor->call(VIDIOC_S_FMT, &
fmt)) {
586 if (errno == EBUSY) {
590 qWarning() <<
"Couldn't set video format on v4l2 camera" << strerror(errno);
594 m_cameraBusy =
false;
596 m_bytesPerLine =
fmt.fmt.pix.bytesperline;
597 m_imageSize = std::max(
fmt.fmt.pix.sizeimage, m_bytesPerLine *
fmt.fmt.pix.height);
599 switch (v4l2_colorspace(
fmt.fmt.pix.colorspace)) {
601 case V4L2_COLORSPACE_DCI_P3:
604 case V4L2_COLORSPACE_REC709:
607 case V4L2_COLORSPACE_JPEG:
610 case V4L2_COLORSPACE_SRGB:
614 case V4L2_COLORSPACE_BT2020:
619 v4l2_streamparm streamParam = {};
620 streamParam.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
622 streamParam.parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
624 streamParam.parm.capture.timeperframe = { (
uint)
num, (
uint)den };
625 m_v4l2FileDescriptor->call(VIDIOC_S_PARM, &streamParam);
627 m_frameDuration = 1000000 * streamParam.parm.capture.timeperframe.numerator
628 / streamParam.parm.capture.timeperframe.denominator;
631void QV4L2Camera::initV4L2MemoryTransfer()
640 if (m_memoryTransfer)
643 if (errno == EBUSY) {
648 qCDebug(qLcV4L2Camera) <<
"Cannot init V4L2_MEMORY_USERPTR; trying V4L2_MEMORY_MMAP";
652 if (!m_memoryTransfer) {
658void QV4L2Camera::stopCapturing()
660 if (!m_memoryTransfer || !m_v4l2FileDescriptor)
663 m_notifier =
nullptr;
665 if (!m_v4l2FileDescriptor->stopStream()) {
668 qWarning() <<
"failed to stop capture";
671 m_memoryTransfer =
nullptr;
672 m_cameraBusy =
false;
675void QV4L2Camera::startCapturing()
677 if (!m_v4l2FileDescriptor)
680 setV4L2CameraFormat();
681 initV4L2MemoryTransfer();
683 if (m_cameraBusy || !m_memoryTransfer)
686 if (!m_v4l2FileDescriptor->startStream()) {
687 qWarning() <<
"Couldn't start v4l2 camera stream";
695 m_firstFrameTime = { -1, -1 };
701 result.setColorSpace(m_colorSpace);
707#include "moc_qv4l2camera_p.cpp"
The QCameraDevice class provides general information about camera devices.
bool isNull() const
Returns true if this QCameraDevice is null or invalid.
QList< QCameraFormat > videoFormats
\qmlproperty CameraFormat QtMultimedia::cameraDevice::videoFormats
QByteArray id
\qmlproperty string QtMultimedia::cameraDevice::id
The QCamera class provides interface for system camera devices.
WhiteBalanceMode
\value WhiteBalanceAuto Auto white balance mode.
TorchMode
\value TorchOff Torch is Off.
FocusMode
\value FocusModeAuto Continuous auto focus mode.
FlashMode
\value FlashOff Flash is Off.
ExposureMode
\value ExposureAuto Automatic mode.
The QMemoryVideoBuffer class provides a system memory allocated video data buffer.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
constexpr int width() const noexcept
Returns the width.
void activated(QSocketDescriptor socket, QSocketNotifier::Type activationEvent, QPrivateSignal)
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
const QChar * constData() const
Returns a pointer to the data stored in the QString.
void zoomTo(float, float=-1.) override
void setManualIsoSensitivity(int) override
void setColorTemperature(int) override
bool isActive() const override
void setFocusMode(QCamera::FocusMode) override
QVideoFrameFormat frameFormat() const override
bool setCameraFormat(const QCameraFormat &format) override
void setTorchMode(QCamera::TorchMode) override
void setFocusDistance(float) override
bool isFocusModeSupported(QCamera::FocusMode mode) const override
void setExposureMode(QCamera::ExposureMode) override
void setActive(bool active) override
bool isWhiteBalanceModeSupported(QCamera::WhiteBalanceMode mode) const override
bool isFlashReady() const override
bool resolveCameraFormat(const QCameraFormat &format)
int isoSensitivity() const override
QV4L2Camera(QCamera *parent)
void setExposureCompensation(float) override
void setFlashMode(QCamera::FlashMode) override
bool isFlashModeSupported(QCamera::FlashMode mode) const override
bool isTorchModeSupported(QCamera::TorchMode mode) const override
void setWhiteBalanceMode(QCamera::WhiteBalanceMode) override
bool isExposureModeSupported(QCamera::ExposureMode mode) const override
void setCamera(const QCameraDevice &camera) override
float exposureTime() const override
void setManualExposureTime(float) override
The QVideoFrame class represents a frame of video data.
Combined button and popup list for selecting options.
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
static int qt_safe_open(const char *pathname, int flags, mode_t mode=0777)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
int qRound(qfloat16 d) noexcept
Q_DECL_COLD_FUNCTION Q_CORE_EXPORT QString qt_error_string(int errorCode=-1)
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
constexpr const T & qBound(const T &min, const T &val, const T &max)
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLsizei GLsizei GLfloat distance
GLint GLsizei GLsizei GLenum format
QLatin1StringView QLatin1String
uint32_t v4l2FormatForPixelFormat(QVideoFrameFormat::PixelFormat format)
QVideoFrameFormat::PixelFormat fmt
static const struct @731 formatMap[]
QVideoFrameFormat::PixelFormat formatForV4L2Format(uint32_t v4l2Format)
uint32_t v4l2FormatForPixelFormat(QVideoFrameFormat::PixelFormat format)
QV4L2MemoryTransferUPtr makeUserPtrMemoryTransfer(QV4L2FileDescriptorPtr fileDescriptor, quint32 imageSize)
QV4L2MemoryTransferUPtr makeMMapMemoryTransfer(QV4L2FileDescriptorPtr fileDescriptor)
bool contains(const AT &t) const noexcept
bool autoExposureSupported
bool colorTemperatureSupported
bool manualExposureSupported
bool autoWhiteBalanceSupported
qint32 minExposureAdjustment
qint32 maxExposureAdjustment