summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Roquetto <rafael.roquetto@qt.io>2022-06-09 13:58:12 +1000
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-06-09 09:14:36 +0000
commit8c498c1728295e88cdce62a2fe236e11632ed7aa (patch)
tree5ef8ca656738a5df319bb1a9ab3f381223d66e29
parentf32c1764ad89c2cc6d6c6fe31f7e2d2e7d2dfe32 (diff)
Refactor QNX camera support
Introduce a brand new QQnxCamera class that models around the QNX camera API, and represents an underlying camera unit. As a result, QQnxCamera is a self-contained and orthogonal class that no longer inherits from QPlatformCamera. A new class called QQnxPlatformCamera has been introduced to provide the QPlatformCamera implementation for QNX. While QQnxCamera remains close to the underlying QNX camera API (including the types being used), QQnxPlatformCamera sits one level up and makes use of a QQnxCamera object to expose it to the Qt-compliant API/types. QQnxCamera also enabled doing without the code duplication in QQnxVideoDevices, vastly simplified that class. Change-Id: I5e09a24d52f4890616c66373dd4529c404b107b2 Reviewed-by: Lars Knoll <lars.knoll@qt.io> (cherry picked from commit e881a1afc08f1b168e743d63a2acc3025f3cb88c) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/plugins/multimedia/qnx/CMakeLists.txt1
-rw-r--r--src/plugins/multimedia/qnx/camera/qqnxcamera.cpp720
-rw-r--r--src/plugins/multimedia/qnx/camera/qqnxcamera_p.h219
-rw-r--r--src/plugins/multimedia/qnx/camera/qqnxcamerahandle_p.h138
-rw-r--r--src/plugins/multimedia/qnx/camera/qqnximagecapture.cpp5
-rw-r--r--src/plugins/multimedia/qnx/camera/qqnxplatformcamera.cpp447
-rw-r--r--src/plugins/multimedia/qnx/camera/qqnxplatformcamera_p.h142
-rw-r--r--src/plugins/multimedia/qnx/capture/qqnxmediacapturesession.cpp5
-rw-r--r--src/plugins/multimedia/qnx/capture/qqnxmediacapturesession_p.h4
-rw-r--r--src/plugins/multimedia/qnx/capture/qqnxmediarecorder.cpp10
-rw-r--r--src/plugins/multimedia/qnx/qqnxmediaintegration.cpp7
-rw-r--r--src/plugins/multimedia/qnx/qqnxmediaintegration_p.h2
-rw-r--r--src/plugins/multimedia/qnx/qqnxvideodevices.cpp122
-rw-r--r--src/plugins/multimedia/qnx/qqnxvideodevices_p.h7
14 files changed, 1367 insertions, 462 deletions
diff --git a/src/plugins/multimedia/qnx/CMakeLists.txt b/src/plugins/multimedia/qnx/CMakeLists.txt
index 18d062343..af7ca686b 100644
--- a/src/plugins/multimedia/qnx/CMakeLists.txt
+++ b/src/plugins/multimedia/qnx/CMakeLists.txt
@@ -5,6 +5,7 @@ qt_internal_add_plugin(QQnxMediaPlugin
SOURCES
SOURCES
camera/qqnxcamera.cpp camera/qqnxcamera_p.h
+ camera/qqnxplatformcamera.cpp camera/qqnxplatformcamera_p.h
camera/qqnxcameraframebuffer.cpp camera/qqnxcameraframebuffer_p.h
camera/qqnximagecapture.cpp camera/qqnximagecapture_p.h
common/qqnxaudioinput.cpp common/qqnxaudioinput_p.h
diff --git a/src/plugins/multimedia/qnx/camera/qqnxcamera.cpp b/src/plugins/multimedia/qnx/camera/qqnxcamera.cpp
index 35008be45..ec238be4f 100644
--- a/src/plugins/multimedia/qnx/camera/qqnxcamera.cpp
+++ b/src/plugins/multimedia/qnx/camera/qqnxcamera.cpp
@@ -46,21 +46,15 @@
#include <private/qmediastoragelocation_p.h>
-static constexpr camera_focusmode_t qnxFocusMode(QCamera::FocusMode mode)
+QDebug &operator<<(QDebug &d, const QQnxCamera::VideoFormat &f)
{
- switch (mode) {
- default:
- case QCamera::FocusModeAuto:
- case QCamera::FocusModeAutoFar:
- case QCamera::FocusModeInfinity:
- return CAMERA_FOCUSMODE_CONTINUOUS_AUTO;
- case QCamera::FocusModeAutoNear:
- return CAMERA_FOCUSMODE_CONTINUOUS_MACRO;
- case QCamera::FocusModeHyperfocal:
- return CAMERA_FOCUSMODE_EDOF;
- case QCamera::FocusModeManual:
- return CAMERA_FOCUSMODE_MANUAL;
- }
+ d << "VideoFormat - width=" << f.width
+ << "height=" << f.height
+ << "rotation=" << f.rotation
+ << "frameRate=" << f.frameRate
+ << "frameType=" << f.frameType;
+
+ return d;
}
static QString statusToString(camera_devstatus_t status)
@@ -101,10 +95,28 @@ static QString statusToString(camera_devstatus_t status)
QT_BEGIN_NAMESPACE
-QQnxCamera::QQnxCamera(QCamera *parent)
- : QPlatformCamera(parent)
+QQnxCamera::QQnxCamera(camera_unit_t unit, QObject *parent)
+ : QObject(parent)
+ , m_cameraUnit(unit)
{
- setCamera(QMediaDevices::defaultVideoInput());
+ if (!m_handle.open(m_cameraUnit, CAMERA_MODE_RW))
+ qWarning("QQnxCamera: Failed to open camera (0x%x)", m_handle.lastError());
+
+ if (camera_set_vf_mode(m_handle.get(), CAMERA_VFMODE_VIDEO) != CAMERA_EOK) {
+ qWarning("QQnxCamera: unable to configure viewfinder mode");
+ return;
+ }
+
+ if (camera_set_vf_property(m_handle.get(), CAMERA_IMGPROP_CREATEWINDOW, 0,
+ CAMERA_IMGPROP_RENDERTOWINDOW, 0) != CAMERA_EOK) {
+ qWarning("QQnxCamera: failed to set camera properties");
+ return;
+ }
+
+ updateZoomLimits();
+ updateSupportedWhiteBalanceValues();
+
+ m_valid = true;
}
QQnxCamera::~QQnxCamera()
@@ -112,43 +124,38 @@ QQnxCamera::~QQnxCamera()
stop();
}
-bool QQnxCamera::isActive() const
-{
- return m_handle.isOpen() && m_viewfinderActive;
-}
-
-void QQnxCamera::setActive(bool active)
+camera_unit_t QQnxCamera::unit() const
{
- if (active)
- start();
- else
- stop();
+ return m_cameraUnit;
}
-void QQnxCamera::start()
+QString QQnxCamera::name() const
{
- if (isActive())
- return;
+ char name[CAMERA_LOCATION_NAMELEN];
- updateCameraFeatures();
-
- if (camera_set_vf_property(m_handle.get(), CAMERA_IMGPROP_CREATEWINDOW, 0,
- CAMERA_IMGPROP_RENDERTOWINDOW, 0) != CAMERA_EOK) {
- qWarning("QQnxCamera: failed to set camera properties");
- return;
+ if (camera_get_location_property(m_cameraUnit,
+ CAMERA_LOCATION_NAME, &name, CAMERA_LOCATION_END) != CAMERA_EOK) {
+ qWarning("QQnxCamera: unable to obtain camera name");
+ return {};
}
- constexpr camera_vfmode_t mode = CAMERA_VFMODE_DEFAULT;
+ return QString::fromUtf8(name);
+}
- if (!supportedVfModes().contains(mode)) {
- qWarning("QQnxCamera: unsupported viewfinder mode");
- return;
- }
+bool QQnxCamera::isValid() const
+{
+ return m_valid;
+}
- if (camera_set_vf_mode(m_handle.get(), mode) != CAMERA_EOK) {
- qWarning("QQnxCamera: unable to configure viewfinder mode");
+bool QQnxCamera::isActive() const
+{
+ return m_handle.isOpen() && m_viewfinderActive;
+}
+
+void QQnxCamera::start()
+{
+ if (isActive())
return;
- }
if (camera_start_viewfinder(m_handle.get(), viewfinderCallback,
statusCallback, this) != CAMERA_EOK) {
@@ -157,12 +164,6 @@ void QQnxCamera::start()
}
m_viewfinderActive = true;
-
- if (m_session)
- m_videoSink = m_session->videoSink();
-
- if (isVideoEncodingSupported() && m_outputUrl.isValid())
- startVideoRecording();
}
void QQnxCamera::stop()
@@ -177,35 +178,17 @@ void QQnxCamera::stop()
qWarning("QQnxCamera: Failed to stop camera");
m_viewfinderActive = false;
-
- m_videoSink = nullptr;
}
-void QQnxCamera::setCamera(const QCameraDevice &camera)
-{
- if (m_camera == camera)
- return;
-
- stop();
-
- m_handle = {};
-
- m_camera = camera;
- m_cameraUnit = camera_unit_t(camera.id().toUInt());
-
- if (!m_handle.open(m_cameraUnit, CAMERA_MODE_RO|CAMERA_MODE_PWRITE))
- qWarning("QQnxCamera: Failed to open camera (0x%x)", m_handle.lastError());
-}
-
-bool QQnxCamera::setCameraFormat(const QCameraFormat &format)
+bool QQnxCamera::setCameraFormat(uint32_t width, uint32_t height, double frameRate)
{
if (!m_handle.isOpen())
return false;
const camera_error_t error = camera_set_vf_property(m_handle.get(),
- CAMERA_IMGPROP_WIDTH, format.resolution().width(),
- CAMERA_IMGPROP_HEIGHT, format.resolution().height(),
- CAMERA_IMGPROP_FRAMERATE, format.maxFrameRate());
+ CAMERA_IMGPROP_WIDTH, width,
+ CAMERA_IMGPROP_HEIGHT, height,
+ CAMERA_IMGPROP_FRAMERATE, frameRate);
if (error != CAMERA_EOK) {
qWarning("QQnxCamera: failed to set camera format");
@@ -215,118 +198,250 @@ bool QQnxCamera::setCameraFormat(const QCameraFormat &format)
return true;
}
-void QQnxCamera::setCaptureSession(QPlatformMediaCaptureSession *session)
+bool QQnxCamera::isFocusModeSupported(camera_focusmode_t mode) const
{
- if (m_session == session)
- return;
- m_session = static_cast<QQnxMediaCaptureSession *>(session);
+ return supportedFocusModes().contains(mode);
}
-bool QQnxCamera::isFocusModeSupported(QCamera::FocusMode mode) const
+bool QQnxCamera::setFocusMode(camera_focusmode_t mode)
{
- return supportedFocusModes().contains(::qnxFocusMode(mode));
+ if (!isActive())
+ return false;
+
+ const camera_error_t result = camera_set_focus_mode(m_handle.get(), mode);
+
+ if (result != CAMERA_EOK) {
+ qWarning("QQnxCamera: Unable to set focus mode (0x%x)", result);
+ return false;
+ }
+
+ focusModeChanged(mode);
+
+ return true;
}
-void QQnxCamera::setFocusMode(QCamera::FocusMode mode)
+camera_focusmode_t QQnxCamera::focusMode() const
{
if (!isActive())
- return;
+ return CAMERA_FOCUSMODE_OFF;
+
+ camera_focusmode_t mode;
- const camera_error_t result = camera_set_focus_mode(m_handle.get(), ::qnxFocusMode(mode));
+ const camera_error_t result = camera_get_focus_mode(m_handle.get(), &mode);
if (result != CAMERA_EOK) {
qWarning("QQnxCamera: Unable to set focus mode (0x%x)", result);
- return;
+ return CAMERA_FOCUSMODE_OFF;
}
- focusModeChanged(mode);
+ return mode;
+}
+
+QQnxCamera::VideoFormat QQnxCamera::vfFormat() const
+{
+ VideoFormat f = {};
+
+ if (camera_get_vf_property(m_handle.get(),
+ CAMERA_IMGPROP_WIDTH, &f.width,
+ CAMERA_IMGPROP_HEIGHT, &f.height,
+ CAMERA_IMGPROP_ROTATION, &f.rotation,
+ CAMERA_IMGPROP_FRAMERATE, &f.frameRate,
+ CAMERA_IMGPROP_FORMAT, &f.frameType) != CAMERA_EOK) {
+ qWarning("QQnxCamera: Failed to query video finder frameType");
+ }
+
+ return f;
+}
+
+void QQnxCamera::setVfFormat(const VideoFormat &f)
+{
+ const bool active = isActive();
+
+ if (active)
+ stop();
+
+ if (camera_set_vf_property(m_handle.get(),
+ CAMERA_IMGPROP_WIDTH, f.width,
+ CAMERA_IMGPROP_HEIGHT, f.height,
+ CAMERA_IMGPROP_ROTATION, f.rotation,
+ CAMERA_IMGPROP_FRAMERATE, f.frameRate,
+ CAMERA_IMGPROP_FORMAT, f.frameType) != CAMERA_EOK) {
+ qWarning("QQnxCamera: Failed to set video finder frameType");
+ }
+
+ if (active)
+ start();
+}
+
+QQnxCamera::VideoFormat QQnxCamera::recordingFormat() const
+{
+ VideoFormat f = {};
+
+ if (camera_get_video_property(m_handle.get(),
+ CAMERA_IMGPROP_WIDTH, &f.width,
+ CAMERA_IMGPROP_HEIGHT, &f.height,
+ CAMERA_IMGPROP_ROTATION, &f.rotation,
+ CAMERA_IMGPROP_FRAMERATE, &f.frameRate,
+ CAMERA_IMGPROP_FORMAT, &f.frameType) != CAMERA_EOK) {
+ qWarning("QQnxCamera: Failed to query recording frameType");
+ }
+
+ return f;
+}
+
+void QQnxCamera::setRecordingFormat(const VideoFormat &f)
+{
+ if (camera_set_video_property(m_handle.get(),
+ CAMERA_IMGPROP_WIDTH, f.width,
+ CAMERA_IMGPROP_HEIGHT, f.height,
+ CAMERA_IMGPROP_ROTATION, f.rotation,
+ CAMERA_IMGPROP_FRAMERATE, f.frameRate,
+ CAMERA_IMGPROP_FORMAT, f.frameType) != CAMERA_EOK) {
+ qWarning("QQnxCamera: Failed to set recording frameType");
+ }
}
void QQnxCamera::setCustomFocusPoint(const QPointF &point)
{
- // get the size of the viewfinder
- int width = 0;
- int height = 0;
- auto result = camera_get_vf_property(m_handle.get(),
- CAMERA_IMGPROP_WIDTH, width,
- CAMERA_IMGPROP_HEIGHT, height);
- if (result != CAMERA_EOK)
+ const QSize vfSize = viewFinderSize();
+
+ if (vfSize.isEmpty())
return;
+ const auto toUint32 = [](double value) {
+ return static_cast<uint32_t>(std::max(0.0, value));
+ };
+
// define a 40x40 pixel focus region around the custom focus point
- camera_region_t focusRegion;
- focusRegion.left = qMax(0, static_cast<int>(point.x() * width) - 20);
- focusRegion.top = qMax(0, static_cast<int>(point.y() * height) - 20);
- focusRegion.width = 40;
- focusRegion.height = 40;
+ constexpr int pixelSize = 40;
- result = camera_set_focus_regions(m_handle.get(), 1, &focusRegion);
- if (result != CAMERA_EOK) {
- qWarning("QQnxCamera: Unable to set focus region (0x%x)", result);
- return;
- }
- auto qnxMode = ::qnxFocusMode(focusMode());
- result = camera_set_focus_mode(m_handle.get(), qnxMode);
- if (result != CAMERA_EOK) {
- qWarning("QQnxCamera: Unable to set focus region (0x%x)", result);
+ const auto left = toUint32(point.x() * vfSize.width() - pixelSize / 2);
+ const auto top = toUint32(point.y() * vfSize.height() - pixelSize / 2);
+
+ camera_region_t focusRegion {
+ .left = left,
+ .top = top,
+ .width = pixelSize,
+ .height = pixelSize,
+ .extra = 0
+ };
+
+ if (camera_set_focus_regions(m_handle.get(), 1, &focusRegion) != CAMERA_EOK) {
+ qWarning("QQnxCamera: Unable to set focus region");
return;
}
- customFocusPointChanged(point);
+
+ if (setFocusMode(focusMode()))
+ customFocusPointChanged(point);
}
-void QQnxCamera::setFocusDistance(float distance)
+void QQnxCamera::setManualFocusStep(int step)
{
- if (!isActive() || !isFocusModeSupported(QCamera::FocusModeManual))
+ if (!isActive()) {
+ qWarning("QQnxCamera: Failed to set focus distance - view finder not active");
return;
+ }
- const int maxDistance = maxFocusDistance();
-
- if (maxDistance < 0)
+ if (!isFocusModeSupported(CAMERA_FOCUSMODE_MANUAL)) {
+ qWarning("QQnxCamera: Failed to set focus distance - manual focus mode not supported");
return;
+ }
- const int qnxDistance = maxDistance * std::min(distance, 1.0f);
-
- if (camera_set_manual_focus_step(m_handle.get(), qnxDistance) != CAMERA_EOK)
+ if (camera_set_manual_focus_step(m_handle.get(), step) != CAMERA_EOK)
qWarning("QQnxCamera: Failed to set focus distance");
}
-int QQnxCamera::maxFocusDistance() const
+int QQnxCamera::manualFocusStep() const
{
- if (!isActive() || !isFocusModeSupported(QCamera::FocusModeManual))
- return -1;
+ return focusStep().step;
+}
- int maxstep;
- int step;
+int QQnxCamera::maxFocusStep() const
+{
+ return focusStep().maxStep;
+}
- if (camera_get_manual_focus_step(m_handle.get(), &maxstep, &step) != CAMERA_EOK) {
+QQnxCamera::FocusStep QQnxCamera::focusStep() const
+{
+ constexpr FocusStep invalidStep { -1, -1 };
+
+ if (!isActive()) {
+ qWarning("QQnxCamera: Failed to query max focus distance - view finder not active");
+ return invalidStep;
+ }
+
+ if (!isFocusModeSupported(CAMERA_FOCUSMODE_MANUAL)) {
+ qWarning("QQnxCamera: Failed to query max focus distance - "
+ "manual focus mode not supported");
+ return invalidStep;
+ }
+
+ FocusStep focusStep;
+
+ if (camera_get_manual_focus_step(m_handle.get(),
+ &focusStep.maxStep, &focusStep.step) != CAMERA_EOK) {
qWarning("QQnxCamera: Unable to query camera focus step");
- return -1;
+ return invalidStep;
}
- return maxstep;
+ return focusStep;
}
-void QQnxCamera::zoomTo(float factor, float)
+
+QSize QQnxCamera::viewFinderSize() const
{
- if (!isActive())
- return;
+ // get the size of the viewfinder
+ int width = 0;
+ int height = 0;
- if (maxZoom <= minZoom)
- return;
- // QNX has an integer based API. Interpolate between the levels according to the factor we get
- const float max = maxZoomFactor();
- const float min = minZoomFactor();
- if (max <= min)
- return;
- factor = qBound(min, factor, max) - min;
- uint zoom = minZoom + (uint)qRound(factor*(maxZoom - minZoom)/(max - min));
+ if (camera_get_vf_property(m_handle.get(),
+ CAMERA_IMGPROP_WIDTH, width,
+ CAMERA_IMGPROP_HEIGHT, height) != CAMERA_EOK) {
+ qWarning("QQnxCamera: failed to query view finder size");
+ return {};
+ }
- auto error = camera_set_vf_property(m_handle.get(), CAMERA_IMGPROP_ZOOMFACTOR, zoom);
- if (error == CAMERA_EOK)
- zoomFactorChanged(factor);
+ return { width, height };
}
-void QQnxCamera::setExposureCompensation(float ev)
+uint32_t QQnxCamera::minimumZoomLevel() const
+{
+ return m_minZoom;
+}
+
+uint32_t QQnxCamera::maximumZoomLevel() const
+{
+ return m_maxZoom;
+}
+
+bool QQnxCamera::isSmoothZoom() const
+{
+ return m_smoothZoom;
+}
+
+double QQnxCamera::zoomRatio(uint32_t zoomLevel) const
+{
+ double ratio;
+
+ if (camera_get_zoom_ratio_from_zoom_level(m_handle.get(), zoomLevel, &ratio) != CAMERA_EOK) {
+ qWarning("QQnxCamera: failed to query zoom ratio from zoom level");
+ return 0.0;
+ }
+
+ return ratio;
+}
+
+bool QQnxCamera::setZoomFactor(uint32_t factor)
+{
+ if (camera_set_vf_property(m_handle.get(), CAMERA_IMGPROP_ZOOMFACTOR, factor) != CAMERA_EOK) {
+ qWarning("QQnxCamera: failed to set zoom factor");
+ return false;
+ }
+
+ return true;
+}
+
+void QQnxCamera::setEvOffset(float ev)
{
if (!isActive())
return;
@@ -335,12 +450,12 @@ void QQnxCamera::setExposureCompensation(float ev)
qWarning("QQnxCamera: Failed to setup exposure compensation");
}
-int QQnxCamera::isoSensitivity() const
+uint32_t QQnxCamera::manualIsoSensitivity() const
{
if (!isActive())
return 0;
- unsigned int isoValue;
+ uint32_t isoValue;
if (camera_get_manual_iso(m_handle.get(), &isoValue) != CAMERA_EOK) {
qWarning("QQnxCamera: Failed to query ISO value");
@@ -350,18 +465,16 @@ int QQnxCamera::isoSensitivity() const
return isoValue;
}
-void QQnxCamera::setManualIsoSensitivity(int value)
+void QQnxCamera::setManualIsoSensitivity(uint32_t value)
{
if (!isActive())
return;
- const unsigned int isoValue = std::max(0, value);
-
- if (camera_set_manual_iso(m_handle.get(), isoValue) != CAMERA_EOK)
+ if (camera_set_manual_iso(m_handle.get(), value) != CAMERA_EOK)
qWarning("QQnxCamera: Failed to set ISO value");
}
-void QQnxCamera::setManualExposureTime(float seconds)
+void QQnxCamera::setManualExposureTime(double seconds)
{
if (!isActive())
return;
@@ -370,95 +483,120 @@ void QQnxCamera::setManualExposureTime(float seconds)
qWarning("QQnxCamera: Failed to set exposure time");
}
-float QQnxCamera::exposureTime() const
+double QQnxCamera::manualExposureTime() const
{
if (!isActive())
- return 0;
+ return 0.0;
double shutterSpeed;
if (camera_get_manual_shutter_speed(m_handle.get(), &shutterSpeed) != CAMERA_EOK) {
qWarning("QQnxCamera: Failed to get exposure time");
- return 0;
+ return 0.0;
}
- return static_cast<float>(shutterSpeed);
+ return shutterSpeed;
}
-bool QQnxCamera::isWhiteBalanceModeSupported(QCamera::WhiteBalanceMode mode) const
+bool QQnxCamera::hasFeature(camera_feature_t feature) const
{
- if (!whiteBalanceModesChecked) {
- whiteBalanceModesChecked = true;
- unsigned numWhiteBalanceValues = 0;
- auto error = camera_get_supported_manual_white_balance_values(m_handle.get(), 0, &numWhiteBalanceValues,
- nullptr, &continuousColorTemperatureSupported);
- if (error == CAMERA_EOK) {
- manualColorTemperatureValues.resize(numWhiteBalanceValues);
- auto error = camera_get_supported_manual_white_balance_values(m_handle.get(), numWhiteBalanceValues, &numWhiteBalanceValues,
- manualColorTemperatureValues.data(),
- &continuousColorTemperatureSupported);
+ return camera_has_feature(m_handle.get(), feature);
+}
- minColorTemperature = 1024*1014; // large enough :)
- for (int temp : qAsConst(manualColorTemperatureValues)) {
- minColorTemperature = qMin(minColorTemperature, temp);
- maxColorTemperature = qMax(maxColorTemperature, temp);
- }
- } else {
- maxColorTemperature = 0;
- }
+void QQnxCamera::setWhiteBalanceMode(camera_whitebalancemode_t mode)
+{
+ if (!isActive())
+ return;
+
+ if (camera_set_whitebalance_mode(m_handle.get(), mode) != CAMERA_EOK)
+ qWarning("QQnxCamera: failed to set whitebalance mode");
+}
+
+camera_whitebalancemode_t QQnxCamera::whiteBalanceMode() const
+{
+ if (!isActive())
+ return CAMERA_WHITEBALANCEMODE_OFF;
+
+ camera_whitebalancemode_t mode;
+
+ if (camera_get_whitebalance_mode(m_handle.get(), &mode) != CAMERA_EOK) {
+ qWarning("QQnxCamera: failed to get white balance mode");
+ return CAMERA_WHITEBALANCEMODE_OFF;
}
- if (maxColorTemperature != 0)
- return true;
- return mode == QCamera::WhiteBalanceAuto;
+ return mode;
}
-void QQnxCamera::setWhiteBalanceMode(QCamera::WhiteBalanceMode mode)
+void QQnxCamera::setManualWhiteBalance(uint32_t value)
{
- if (mode == QCamera::WhiteBalanceAuto) {
- camera_set_whitebalance_mode(m_handle.get(), CAMERA_WHITEBALANCEMODE_AUTO);
+ if (!isActive())
return;
- }
- camera_set_whitebalance_mode(m_handle.get(), CAMERA_WHITEBALANCEMODE_MANUAL);
- setColorTemperature(colorTemperatureForWhiteBalance(mode));
+
+ if (camera_set_manual_white_balance(m_handle.get(), value) != CAMERA_EOK)
+ qWarning("QQnxCamera: failed to set manual white balance");
}
-void QQnxCamera::setColorTemperature(int temperature)
+uint32_t QQnxCamera::manualWhiteBalance() const
{
+ if (!isActive())
+ return 0;
- if (maxColorTemperature == 0)
- return;
+ uint32_t value;
- unsigned bestTemp = 0;
- if (!continuousColorTemperatureSupported) {
- // find the closest match
- int delta = 1024*1024;
- for (unsigned temp : qAsConst(manualColorTemperatureValues)) {
- int d = qAbs(int(temp) - temperature);
- if (d < delta) {
- bestTemp = temp;
- delta = d;
- }
- }
- } else {
- bestTemp = (unsigned)qBound(minColorTemperature, temperature, maxColorTemperature);
+ if (camera_get_manual_white_balance(m_handle.get(), &value) != CAMERA_EOK) {
+ qWarning("QQnxCamera: failed to get manual white balance");
+ return 0;
}
- auto error = camera_set_manual_white_balance(m_handle.get(), bestTemp);
+ return value;
}
-void QQnxCamera::startVideoRecording()
+bool QQnxCamera::startVideoRecording(const QString &filename)
{
- const QString container = m_encoderSettings.mimeType().preferredSuffix();
- const QString location = QMediaStorageLocation::generateFileName(m_outputUrl.toLocalFile(),
- QStandardPaths::MoviesLocation, container);
+ // when preview is video, we must ensure that the recording properties
+ // match the view finder properties
+ if (hasFeature(CAMERA_FEATURE_PREVIEWISVIDEO)) {
+ VideoFormat newFormat = vfFormat();
- if (camera_start_video(m_handle.get(), qPrintable(location),
- nullptr, nullptr, nullptr) != CAMERA_EOK) {
- qWarning("QQnxCamera: failed to start video encoding");
- } else {
+ const QList<camera_frametype_t> recordingTypes = supportedRecordingFrameTypes();
+
+ // find a suitable matching frame type in case the current view finder
+ // frametype is not supported
+ if (newFormat.frameType != recordingFormat().frameType
+ && !recordingTypes.contains(newFormat.frameType)) {
+
+ bool found = false;
+
+ for (const camera_frametype_t type : supportedVfFrameTypes()) {
+ if (recordingTypes.contains(type)) {
+ newFormat.frameType = type;
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ m_originalVfFormat = vfFormat();
+
+ // reconfigure and restart the view finder
+ setVfFormat(newFormat);
+ } else {
+ qWarning("QQnxCamera: failed to find suitable frame type for recording - aborting");
+ return false;
+ }
+ }
+
+ setRecordingFormat(newFormat);
+ }
+
+ if (camera_start_video(m_handle.get(), qPrintable(filename),
+ nullptr, nullptr, nullptr) == CAMERA_EOK) {
m_recordingVideo = true;
+ } else {
+ qWarning("QQnxCamera: failed to start video encoding");
}
+
+ return m_recordingVideo;
}
void QQnxCamera::stopVideoRecording()
@@ -467,6 +605,12 @@ void QQnxCamera::stopVideoRecording()
if (camera_stop_video(m_handle.get()) != CAMERA_EOK)
qWarning("QQnxCamera: error when stopping video recording");
+
+ // restore original vf format
+ if (m_originalVfFormat) {
+ setVfFormat(*m_originalVfFormat);
+ m_originalVfFormat.reset();
+ }
}
bool QQnxCamera::isVideoEncodingSupported() const
@@ -477,47 +621,50 @@ bool QQnxCamera::isVideoEncodingSupported() const
return camera_has_feature(m_handle.get(), CAMERA_FEATURE_VIDEO);
}
-void QQnxCamera::setOutputUrl(const QUrl &url)
+camera_handle_t QQnxCamera::handle() const
{
- m_outputUrl = url;
+ return m_handle.get();
}
-void QQnxCamera::setMediaEncoderSettings(const QMediaEncoderSettings &settings)
+void QQnxCamera::updateZoomLimits()
{
- m_encoderSettings = settings;
-}
+ bool smooth;
-camera_handle_t QQnxCamera::handle() const
-{
- return m_handle.get();
+ if (camera_get_zoom_limits(m_handle.get(), &m_minZoom, &m_maxZoom, &smooth) != CAMERA_EOK) {
+ qWarning("QQnxCamera: failed to update zoom limits - using default values");
+ m_minZoom = m_maxZoom = 0;
+ }
}
-void QQnxCamera::updateCameraFeatures()
+void QQnxCamera::updateSupportedWhiteBalanceValues()
{
- whiteBalanceModesChecked = false;
+ uint32_t numSupported = 0;
- bool smooth;
- const camera_error_t error = camera_get_zoom_limits(m_handle.get(),
- &minZoom, &maxZoom, &smooth);
-
- if (error == CAMERA_EOK) {
- double level;
- camera_get_zoom_ratio_from_zoom_level(m_handle.get(), minZoom, &level);
- minimumZoomFactorChanged(level);
- camera_get_zoom_ratio_from_zoom_level(m_handle.get(), maxZoom, &level);
- maximumZoomFactorChanged(level);
- } else {
- minZoom = maxZoom = 1;
+ const camera_error_t result = camera_get_supported_manual_white_balance_values(
+ m_handle.get(), 0, &numSupported, nullptr, &m_continuousWhiteBalanceValues);
+
+ if (result != CAMERA_EOK) {
+ if (result == CAMERA_EOPNOTSUPP)
+ qWarning("QQnxCamera: white balance not supported");
+ else
+ qWarning("QQnxCamera: unable to query manual white balance value count");
+
+ m_supportedWhiteBalanceValues.clear();
+
+ return;
}
- QCamera::Features features = {};
+ m_supportedWhiteBalanceValues.resize(numSupported);
- if (camera_has_feature(m_handle.get(), CAMERA_FEATURE_REGIONFOCUS))
- features |= QCamera::Feature::CustomFocusPoint;
+ if (camera_get_supported_manual_white_balance_values(m_handle.get(),
+ m_supportedWhiteBalanceValues.size(),
+ &numSupported,
+ m_supportedWhiteBalanceValues.data(),
+ &m_continuousWhiteBalanceValues) != CAMERA_EOK) {
+ qWarning("QQnxCamera: unable to query manual white balance values");
- minimumZoomFactorChanged(minZoom);
- maximumZoomFactorChanged(maxZoom);
- supportedFeaturesChanged(features);
+ m_supportedWhiteBalanceValues.clear();
+ }
}
QList<camera_vfmode_t> QQnxCamera::supportedVfModes() const
@@ -530,19 +677,78 @@ QList<camera_res_t> QQnxCamera::supportedVfResolutions() const
return queryValues(camera_get_supported_vf_resolutions);
}
+QList<camera_frametype_t> QQnxCamera::supportedVfFrameTypes() const
+{
+ return queryValues(camera_get_supported_vf_frame_types);
+}
+
QList<camera_focusmode_t> QQnxCamera::supportedFocusModes() const
{
return queryValues(camera_get_focus_modes);
}
+QList<double> QQnxCamera::specifiedVfFrameRates(camera_frametype_t frameType,
+ camera_res_t resolution) const
+{
+ uint32_t numSupported = 0;
+
+ if (camera_get_specified_vf_framerates(m_handle.get(), frameType, resolution,
+ 0, &numSupported, nullptr, nullptr) != CAMERA_EOK) {
+ qWarning("QQnxCamera: unable to query specified framerates count");
+ return {};
+ }
+
+ QList<double> values(numSupported);
+
+ if (camera_get_specified_vf_framerates(m_handle.get(), frameType, resolution,
+ values.size(), &numSupported, values.data(), nullptr) != CAMERA_EOK) {
+ qWarning("QQnxCamera: unable to query specified framerates values");
+ return {};
+ }
+
+ return values;
+}
+
+QList<camera_frametype_t> QQnxCamera::supportedRecordingFrameTypes() const
+{
+ return queryValues(camera_get_video_frame_types);
+}
+
+QList<uint32_t> QQnxCamera::supportedWhiteBalanceValues() const
+{
+ return m_supportedWhiteBalanceValues;
+}
+
+bool QQnxCamera::hasContinuousWhiteBalanceValues() const
+{
+ return m_continuousWhiteBalanceValues;
+}
+
+QList<camera_unit_t> QQnxCamera::supportedUnits()
+{
+ unsigned int numSupported = 0;
+
+ if (camera_get_supported_cameras(0, &numSupported, nullptr) != CAMERA_EOK) {
+ qWarning("QQnxCamera: failed to query supported camera unit count");
+ return {};
+ }
+
+ QList<camera_unit_t> cameraUnits(numSupported);
+
+ if (camera_get_supported_cameras(cameraUnits.size(), &numSupported,
+ cameraUnits.data()) != CAMERA_EOK) {
+ qWarning("QQnxCamera: failed to enumerate supported camera units");
+ return {};
+ }
+
+ return cameraUnits;
+}
+
template <typename T, typename U>
QList<T> QQnxCamera::queryValues(QueryFuncPtr<T,U> func) const
{
static_assert(std::is_integral_v<U>, "Parameter U must be of integral type");
- if (!isActive())
- return {};
-
U numSupported = 0;
if (func(m_handle.get(), 0, &numSupported, nullptr) != CAMERA_EOK) {
@@ -562,9 +768,6 @@ QList<T> QQnxCamera::queryValues(QueryFuncPtr<T,U> func) const
void QQnxCamera::handleVfBuffer(camera_buffer_t *buffer)
{
- if (!m_videoSink)
- return;
-
// process the frame on this thread before locking the mutex
auto frame = std::make_unique<QQnxCameraFrameBuffer>(buffer);
@@ -573,9 +776,8 @@ void QQnxCamera::handleVfBuffer(camera_buffer_t *buffer)
m_currentFrame = std::move(frame);
m_currentFrameMutex.unlock();
- QMetaObject::invokeMethod(this, "processFrame", Qt::QueuedConnection);
+ Q_EMIT frameAvailable();
}
-
}
void QQnxCamera::handleVfStatus(camera_devstatus_t status, uint16_t extraData)
@@ -590,34 +792,46 @@ void QQnxCamera::handleStatusChange(camera_devstatus_t status, uint16_t extraDat
Q_UNUSED(extraData);
switch (status) {
- case CAMERA_STATUS_DISCONNECTED:
- case CAMERA_STATUS_POWERDOWN:
- case CAMERA_STATUS_VIDEOVF:
+ case CAMERA_STATUS_BUFFER_UNDERFLOW:
+ case CAMERA_STATUS_CAPTURECOMPLETE:
case CAMERA_STATUS_CAPTURE_ABORTED:
+ case CAMERA_STATUS_CONNECTED:
+ case CAMERA_STATUS_DISCONNECTED:
+ case CAMERA_STATUS_FILESIZE_ERROR:
+ case CAMERA_STATUS_FILESIZE_LIMIT_WARNING:
case CAMERA_STATUS_FILESIZE_WARNING:
+ case CAMERA_STATUS_FLASH_LEVEL_CHANGE:
case CAMERA_STATUS_FOCUS_CHANGE:
- case CAMERA_STATUS_RESOURCENOTAVAIL:
- case CAMERA_STATUS_VIEWFINDER_ERROR:
+ case CAMERA_STATUS_FRAME_DROPPED:
+ case CAMERA_STATUS_LOWLIGHT:
case CAMERA_STATUS_MM_ERROR:
- case CAMERA_STATUS_FILESIZE_ERROR:
case CAMERA_STATUS_NOSPACE_ERROR:
- case CAMERA_STATUS_BUFFER_UNDERFLOW:
- Q_EMIT(status, ::statusToString(status));
- stop();
- break;
- default:
+ case CAMERA_STATUS_PHOTOVF:
+ case CAMERA_STATUS_POWERDOWN:
+ case CAMERA_STATUS_POWERUP:
+ case CAMERA_STATUS_RESOURCENOTAVAIL:
+ case CAMERA_STATUS_UNKNOWN:
+ case CAMERA_STATUS_VIDEOLIGHT_CHANGE:
+ case CAMERA_STATUS_VIDEOLIGHT_LEVEL_CHANGE:
+ case CAMERA_STATUS_VIDEOVF:
+ case CAMERA_STATUS_VIDEO_PAUSE:
+ case CAMERA_STATUS_VIDEO_RESUME:
+ case CAMERA_STATUS_VIEWFINDER_ACTIVE:
+ case CAMERA_STATUS_VIEWFINDER_ERROR:
+ case CAMERA_STATUS_VIEWFINDER_FREEZE:
+ case CAMERA_STATUS_VIEWFINDER_SUSPEND:
+ case CAMERA_STATUS_VIEWFINDER_UNFREEZE:
+ case CAMERA_STATUS_VIEWFINDER_UNSUSPEND:
+ qDebug() << "QQnxCamera:" << ::statusToString(status);
break;
}
}
-void QQnxCamera::processFrame()
+std::unique_ptr<QQnxCameraFrameBuffer> QQnxCamera::takeCurrentFrame()
{
QMutexLocker l(&m_currentFrameMutex);
- const QVideoFrame actualFrame(m_currentFrame.get(),
- QVideoFrameFormat(m_currentFrame->size(), m_currentFrame->pixelFormat()));
-
- m_videoSink->setVideoFrame(actualFrame);
+ return std::move(m_currentFrame);
}
void QQnxCamera::viewfinderCallback(camera_handle_t handle, camera_buffer_t *buffer, void *arg)
diff --git a/src/plugins/multimedia/qnx/camera/qqnxcamera_p.h b/src/plugins/multimedia/qnx/camera/qqnxcamera_p.h
index aab112000..540d8bf4c 100644
--- a/src/plugins/multimedia/qnx/camera/qqnxcamera_p.h
+++ b/src/plugins/multimedia/qnx/camera/qqnxcamera_p.h
@@ -36,8 +36,8 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef QQnxCamera_H
-#define QQnxCamera_H
+#ifndef QQNXCAMERA_H
+#define QQNXCAMERA_H
//
// W A R N I N G
@@ -50,17 +50,18 @@
// We mean it.
//
-#include <private/qplatformcamera_p.h>
-#include <private/qplatformmediarecorder_p.h>
+#include "qqnxcamerahandle_p.h"
#include <QtCore/qlist.h>
#include <QtCore/qmutex.h>
+#include <QtCore/qobject.h>
#include <QtCore/qurl.h>
#include <camera/camera_api.h>
#include <camera/camera_3a.h>
#include <memory>
+#include <optional>
QT_BEGIN_NAMESPACE
@@ -68,156 +69,128 @@ class QQnxCameraFrameBuffer;
class QQnxMediaCaptureSession;
class QQnxVideoSink;
-class CameraHandle
+class QQnxCamera : public QObject
{
+ Q_OBJECT
public:
- CameraHandle() = default;
+ explicit QQnxCamera(camera_unit_t unit, QObject *parent = nullptr);
+ ~QQnxCamera();
- explicit CameraHandle(camera_handle_t h)
- : m_handle (h) {}
+ camera_unit_t unit() const;
- explicit CameraHandle(CameraHandle &&other)
- : m_handle(other.m_handle)
- , m_lastError(other.m_lastError)
- {
- other = CameraHandle();
- }
+ QString name() const;
- CameraHandle(const CameraHandle&) = delete;
+ bool isValid() const;
- CameraHandle& operator=(CameraHandle&& other)
- {
- m_handle = other.m_handle;
- m_lastError = other.m_lastError;
+ bool isActive() const;
+ void start();
+ void stop();
- other = CameraHandle();
+ bool startVideoRecording(const QString &filename);
+ void stopVideoRecording();
- return *this;
- }
+ bool setCameraFormat(uint32_t width, uint32_t height, double frameRate);
- ~CameraHandle()
- {
- close();
- }
+ bool isFocusModeSupported(camera_focusmode_t mode) const;
+ bool setFocusMode(camera_focusmode_t mode);
+ camera_focusmode_t focusMode() const;
- bool open(camera_unit_t unit, uint32_t mode)
- {
- if (isOpen()) {
- m_lastError = CAMERA_EALREADY;
- return false;
- }
+ void setCustomFocusPoint(const QPointF &point);
- return cacheError(camera_open, unit, mode, &m_handle);
- }
+ void setManualFocusStep(int step);
+ int manualFocusStep() const;
+ int maxFocusStep() const;
- bool close()
- {
- if (!isOpen())
- return true;
+ QSize viewFinderSize() const;
- const bool success = cacheError(camera_close, m_handle);
- m_handle = CAMERA_HANDLE_INVALID;
+ uint32_t minimumZoomLevel() const;
+ uint32_t maximumZoomLevel() const;
+ bool isSmoothZoom() const;
+ double zoomRatio(uint32_t zoomLevel) const;
+ bool setZoomFactor(uint32_t factor);
- return success;
- }
+ void setEvOffset(float ev);
- camera_handle_t get() const
- {
- return m_handle;
- }
+ uint32_t manualIsoSensitivity() const;
+ void setManualIsoSensitivity(uint32_t value);
+ void setManualExposureTime(double seconds);
+ double manualExposureTime() const;
- bool isOpen() const
- {
- return m_handle != CAMERA_HANDLE_INVALID;
- }
+ void setWhiteBalanceMode(camera_whitebalancemode_t mode);
+ camera_whitebalancemode_t whiteBalanceMode() const;
- camera_error_t lastError() const
- {
- return m_lastError;
- }
-
-private:
- template <typename Func, typename ...Args>
- bool cacheError(Func f, Args &&...args)
- {
- m_lastError = f(std::forward<Args>(args)...);
-
- return m_lastError == CAMERA_EOK;
- }
+ void setManualWhiteBalance(uint32_t value);
+ uint32_t manualWhiteBalance() const;
- camera_handle_t m_handle = CAMERA_HANDLE_INVALID;
- camera_error_t m_lastError = CAMERA_EOK;
-};
+ bool hasFeature(camera_feature_t feature) const;
+ camera_handle_t handle() const;
-class QQnxCamera : public QPlatformCamera
-{
- Q_OBJECT
-public:
- explicit QQnxCamera(QCamera *parent);
- ~QQnxCamera();
-
- bool isActive() const override;
- void setActive(bool active) override;
- void start();
- void stop();
+ QList<camera_vfmode_t> supportedVfModes() const;
+ QList<camera_res_t> supportedVfResolutions() const;
+ QList<camera_frametype_t> supportedVfFrameTypes() const;
+ QList<camera_focusmode_t> supportedFocusModes() const;
+ QList<double> specifiedVfFrameRates(camera_frametype_t frameType,
+ camera_res_t resolution) const;
- void setCamera(const QCameraDevice &camera) override;
+ QList<camera_frametype_t> supportedRecordingFrameTypes() const;
- bool setCameraFormat(const QCameraFormat &format) override;
+ QList<uint32_t> supportedWhiteBalanceValues() const;
- void setCaptureSession(QPlatformMediaCaptureSession *session) override;
+ bool hasContinuousWhiteBalanceValues() const;
- bool isFocusModeSupported(QCamera::FocusMode mode) const override;
- void setFocusMode(QCamera::FocusMode mode) override;
+ static QList<camera_unit_t> supportedUnits();
- void setCustomFocusPoint(const QPointF &point) override;
+ std::unique_ptr<QQnxCameraFrameBuffer> takeCurrentFrame();
- void setFocusDistance(float distance) override;
+Q_SIGNALS:
+ void focusModeChanged(camera_focusmode_t mode);
+ void customFocusPointChanged(const QPointF &point);
+ void minimumZoomFactorChanged(double factor);
- int maxFocusDistance() const;
+ double maximumZoomFactorChanged(double factor);
- void zoomTo(float /*newZoomFactor*/, float /*rate*/ = -1.) override;
+ void frameAvailable();
- void setExposureCompensation(float ev) override;
+private:
+ struct FocusStep
+ {
+ int step; // current step
+ int maxStep; // max supported step
+ };
- int isoSensitivity() const override;
- void setManualIsoSensitivity(int value) override;
- void setManualExposureTime(float seconds) override;
- float exposureTime() const override;
+ FocusStep focusStep() const;
- bool isWhiteBalanceModeSupported(QCamera::WhiteBalanceMode mode) const override;
- void setWhiteBalanceMode(QCamera::WhiteBalanceMode /*mode*/) override;
- void setColorTemperature(int /*temperature*/) override;
+ struct VideoFormat
+ {
+ uint32_t width;
+ uint32_t height;
+ uint32_t rotation;
+ double frameRate;
+ camera_frametype_t frameType;
+ };
- void setOutputUrl(const QUrl &url);
- void setMediaEncoderSettings(const QMediaEncoderSettings &settings);
+ friend QDebug &operator<<(QDebug&, const VideoFormat&);
- camera_handle_t handle() const;
+ VideoFormat vfFormat() const;
+ void setVfFormat(const VideoFormat &format);
- QList<camera_vfmode_t> supportedVfModes() const;
- QList<camera_res_t> supportedVfResolutions() const;
- QList<camera_focusmode_t> supportedFocusModes() const;
+ VideoFormat recordingFormat() const;
+ void setRecordingFormat(const VideoFormat &format);
-private:
- void updateCameraFeatures();
+ void updateZoomLimits();
+ void updateSupportedWhiteBalanceValues();
void setColorTemperatureInternal(unsigned temp);
- void startVideoRecording();
- void stopVideoRecording();
-
bool isVideoEncodingSupported() const;
void handleVfBuffer(camera_buffer_t *buffer);
- Q_INVOKABLE void processFrame();
-
// viewfinder callback
void handleVfStatus(camera_devstatus_t status, uint16_t extraData);
// our handler running on main thread
- void handleStatusChange(camera_devstatus_t status, uint16_t extraData);
-
+ Q_INVOKABLE void handleStatusChange(camera_devstatus_t status, uint16_t extraData);
template <typename T, typename U>
using QueryFuncPtr = camera_error_t (*)(camera_handle_t, U, U *, T *);
@@ -225,9 +198,6 @@ private:
template <typename T, typename U>
QList<T> queryValues(QueryFuncPtr<T, U> func) const;
- template <typename ...Args>
- using CamAPIFunc = camera_error_t (*)(camera_handle_t, Args...);
-
static void viewfinderCallback(camera_handle_t handle,
camera_buffer_t *buffer, void *arg);
@@ -235,35 +205,32 @@ private:
uint16_t extraData, void *arg);
QQnxMediaCaptureSession *m_session = nullptr;
- QQnxVideoSink *m_videoSink = nullptr;
- QCameraDevice m_camera;
camera_unit_t m_cameraUnit = CAMERA_UNIT_NONE;
- QUrl m_outputUrl;
-
- QMediaEncoderSettings m_encoderSettings;
-
- CameraHandle m_handle;
+ QQnxCameraHandle m_handle;
- uint minZoom = 1;
- uint maxZoom = 1;
- mutable bool whiteBalanceModesChecked = false;
- mutable bool continuousColorTemperatureSupported = false;
- mutable int minColorTemperature = 0;
- mutable int maxColorTemperature = 0;
- mutable QList<unsigned> manualColorTemperatureValues;
+ uint32_t m_minZoom = 0;
+ uint32_t m_maxZoom = 0;
QMutex m_currentFrameMutex;
+ QList<uint32_t> m_supportedWhiteBalanceValues;
+
std::unique_ptr<QQnxCameraFrameBuffer> m_currentFrame;
+ std::optional<VideoFormat> m_originalVfFormat;
+
bool m_viewfinderActive = false;
bool m_recordingVideo = false;
+ bool m_valid = false;
+ bool m_smoothZoom = false;
+ bool m_continuousWhiteBalanceValues = false;
};
QT_END_NAMESPACE
Q_DECLARE_METATYPE(camera_devstatus_t)
+Q_DECLARE_METATYPE(uint16_t)
#endif
diff --git a/src/plugins/multimedia/qnx/camera/qqnxcamerahandle_p.h b/src/plugins/multimedia/qnx/camera/qqnxcamerahandle_p.h
new file mode 100644
index 000000000..1a7ec1d8e
--- /dev/null
+++ b/src/plugins/multimedia/qnx/camera/qqnxcamerahandle_p.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QQNXCAMERAHANDLE_P_H
+#define QQNXCAMERAHANDLE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <camera/camera_api.h>
+
+#include <utility>
+
+class QQnxCameraHandle
+{
+public:
+ QQnxCameraHandle() = default;
+
+ explicit QQnxCameraHandle(camera_handle_t h)
+ : m_handle (h) {}
+
+ explicit QQnxCameraHandle(QQnxCameraHandle &&other)
+ : m_handle(other.m_handle)
+ , m_lastError(other.m_lastError)
+ {
+ other = QQnxCameraHandle();
+ }
+
+ QQnxCameraHandle(const QQnxCameraHandle&) = delete;
+
+ QQnxCameraHandle& operator=(QQnxCameraHandle&& other)
+ {
+ m_handle = other.m_handle;
+ m_lastError = other.m_lastError;
+
+ other = QQnxCameraHandle();
+
+ return *this;
+ }
+
+ ~QQnxCameraHandle()
+ {
+ close();
+ }
+
+ bool open(camera_unit_t unit, uint32_t mode)
+ {
+ if (isOpen()) {
+ m_lastError = CAMERA_EALREADY;
+ return false;
+ }
+
+ return cacheError(camera_open, unit, mode, &m_handle);
+ }
+
+ bool close()
+ {
+ if (!isOpen())
+ return true;
+
+ const bool success = cacheError(camera_close, m_handle);
+ m_handle = CAMERA_HANDLE_INVALID;
+
+ return success;
+ }
+
+ camera_handle_t get() const
+ {
+ return m_handle;
+ }
+
+ bool isOpen() const
+ {
+ return m_handle != CAMERA_HANDLE_INVALID;
+ }
+
+ camera_error_t lastError() const
+ {
+ return m_lastError;
+ }
+
+private:
+ template <typename Func, typename ...Args>
+ bool cacheError(Func f, Args &&...args)
+ {
+ m_lastError = f(std::forward<Args>(args)...);
+
+ return m_lastError == CAMERA_EOK;
+ }
+
+ camera_handle_t m_handle = CAMERA_HANDLE_INVALID;
+ camera_error_t m_lastError = CAMERA_EOK;
+};
+
+#endif
diff --git a/src/plugins/multimedia/qnx/camera/qqnximagecapture.cpp b/src/plugins/multimedia/qnx/camera/qqnximagecapture.cpp
index 6557267b2..3d9ad1193 100644
--- a/src/plugins/multimedia/qnx/camera/qqnximagecapture.cpp
+++ b/src/plugins/multimedia/qnx/camera/qqnximagecapture.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qqnximagecapture_p.h"
+#include "qqnxplatformcamera_p.h"
#include "qqnxmediacapturesession_p.h"
#include "qqnxcamera_p.h"
#include "qfile.h"
@@ -55,7 +56,7 @@ bool QQnxImageCapture::isReadyForCapture() const
{
if (!m_session)
return false;
- auto *camera = static_cast<QQnxCamera *>(m_session->camera());
+ auto *camera = static_cast<QQnxPlatformCamera *>(m_session->camera());
// ### add can take photo
return camera && camera->isActive();
}
@@ -141,7 +142,7 @@ static void imageCaptureImageCallback(camera_handle_t handle, camera_buffer_t *b
int QQnxImageCapture::capture(const QString &fileName)
{
- auto *camera = static_cast<QQnxCamera *>(m_session->camera());
+ auto *camera = static_cast<QQnxPlatformCamera *>(m_session->camera());
// ### add can take photo
if (!camera || !camera->isActive()) {
emit error(-1, QImageCapture::NotReadyError, QPlatformImageCapture::msgCameraNotReady());
diff --git a/src/plugins/multimedia/qnx/camera/qqnxplatformcamera.cpp b/src/plugins/multimedia/qnx/camera/qqnxplatformcamera.cpp
new file mode 100644
index 000000000..ede2f4c88
--- /dev/null
+++ b/src/plugins/multimedia/qnx/camera/qqnxplatformcamera.cpp
@@ -0,0 +1,447 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Research In Motion
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qqnxplatformcamera_p.h"
+#include "qqnxcameraframebuffer_p.h"
+#include "qqnxmediacapturesession_p.h"
+#include "qqnxvideosink_p.h"
+
+#include <qcameradevice.h>
+#include <qmediadevices.h>
+
+#include <private/qmediastoragelocation_p.h>
+
+#include <camera/camera_api.h>
+#include <camera/camera_3a.h>
+
+#include <algorithm>
+#include <array>
+
+#include <dlfcn.h>
+
+struct FocusModeMapping
+{
+ QCamera::FocusMode qt;
+ camera_focusmode_t qnx;
+};
+
+constexpr std::array<FocusModeMapping, 6> focusModes {{
+ { QCamera::FocusModeAuto, CAMERA_FOCUSMODE_CONTINUOUS_AUTO },
+ { QCamera::FocusModeAutoFar, CAMERA_FOCUSMODE_CONTINUOUS_AUTO },
+ { QCamera::FocusModeInfinity, CAMERA_FOCUSMODE_CONTINUOUS_AUTO },
+ { QCamera::FocusModeAutoNear, CAMERA_FOCUSMODE_CONTINUOUS_MACRO },
+ { QCamera::FocusModeHyperfocal, CAMERA_FOCUSMODE_EDOF },
+ { QCamera::FocusModeManual, CAMERA_FOCUSMODE_MANUAL },
+}};
+
+template <typename Mapping, typename From, typename To, size_t N>
+static constexpr To convert(const std::array<Mapping, N> &mapping,
+ From Mapping::* from, To Mapping::* to, From value, To defaultValue)
+{
+ for (const Mapping &m : mapping) {
+ const auto fromValue = m.*from;
+ const auto toValue = m.*to;
+
+ if (value == fromValue)
+ return toValue;
+ }
+
+ return defaultValue;
+}
+
+static constexpr camera_focusmode_t qnxFocusMode(QCamera::FocusMode mode)
+{
+ return convert(focusModes, &FocusModeMapping::qt,
+ &FocusModeMapping::qnx, mode, CAMERA_FOCUSMODE_CONTINUOUS_AUTO);
+}
+
+static constexpr QCamera::FocusMode qtFocusMode(camera_focusmode_t mode)
+{
+ return convert(focusModes, &FocusModeMapping::qnx,
+ &FocusModeMapping::qt, mode, QCamera::FocusModeAuto);
+}
+
+QT_BEGIN_NAMESPACE
+
+QQnxPlatformCamera::QQnxPlatformCamera(QCamera *parent)
+ : QPlatformCamera(parent)
+{
+ if (parent)
+ setCamera(parent->cameraDevice());
+ else
+ setCamera(QMediaDevices::defaultVideoInput());
+}
+
+QQnxPlatformCamera::~QQnxPlatformCamera()
+{
+ stop();
+}
+
+bool QQnxPlatformCamera::isActive() const
+{
+ return m_qnxCamera && m_qnxCamera->isActive();
+}
+
+void QQnxPlatformCamera::setActive(bool active)
+{
+ if (active)
+ start();
+ else
+ stop();
+}
+
+void QQnxPlatformCamera::start()
+{
+ if (!m_qnxCamera || isActive())
+ return;
+
+ if (m_session)
+ m_videoSink = m_session->videoSink();
+
+ m_qnxCamera->start();
+
+ Q_EMIT activeChanged(true);
+}
+
+void QQnxPlatformCamera::stop()
+{
+ if (!m_qnxCamera)
+ return;
+
+ m_qnxCamera->stop();
+
+ m_videoSink = nullptr;
+
+ Q_EMIT activeChanged(false);
+}
+
+void QQnxPlatformCamera::setCamera(const QCameraDevice &camera)
+{
+ if (m_cameraDevice == camera)
+ return;
+
+ const auto cameraUnit = static_cast<camera_unit_t>(camera.id().toUInt());
+
+ m_qnxCamera = std::make_unique<QQnxCamera>(cameraUnit);
+
+ connect(m_qnxCamera.get(), &QQnxCamera::focusModeChanged,
+ [this](camera_focusmode_t mode) { Q_EMIT focusModeChanged(qtFocusMode(mode)); });
+ connect(m_qnxCamera.get(), &QQnxCamera::customFocusPointChanged,
+ this, &QQnxPlatformCamera::customFocusPointChanged);
+ connect(m_qnxCamera.get(), &QQnxCamera::frameAvailable,
+ this, &QQnxPlatformCamera::onFrameAvailable, Qt::QueuedConnection);
+
+ m_cameraDevice = camera;
+
+ updateCameraFeatures();
+}
+
+bool QQnxPlatformCamera::setCameraFormat(const QCameraFormat &format)
+{
+ const QSize resolution = format.resolution();
+
+ if (resolution.isEmpty()) {
+ qWarning("QQnxPlatformCamera: invalid resolution requested");
+ return false;
+ }
+
+ return m_qnxCamera->setCameraFormat(resolution.width(),
+ resolution.height(), format.maxFrameRate());
+}
+
+void QQnxPlatformCamera::setCaptureSession(QPlatformMediaCaptureSession *session)
+{
+ if (m_session == session)
+ return;
+
+ m_session = static_cast<QQnxMediaCaptureSession *>(session);
+}
+
+bool QQnxPlatformCamera::isFocusModeSupported(QCamera::FocusMode mode) const
+{
+ if (!m_qnxCamera)
+ return false;
+
+ return m_qnxCamera->supportedFocusModes().contains(::qnxFocusMode(mode));
+}
+
+void QQnxPlatformCamera::setFocusMode(QCamera::FocusMode mode)
+{
+ if (!m_qnxCamera)
+ return;
+
+ m_qnxCamera->setFocusMode(::qnxFocusMode(mode));
+}
+
+void QQnxPlatformCamera::setCustomFocusPoint(const QPointF &point)
+{
+ if (!m_qnxCamera)
+ return;
+
+ m_qnxCamera->setCustomFocusPoint(point);
+}
+
+void QQnxPlatformCamera::setFocusDistance(float distance)
+{
+ if (!m_qnxCamera)
+ return;
+
+ const int maxDistance = m_qnxCamera->maxFocusStep();
+
+ if (maxDistance < 0)
+ return;
+
+ const int qnxDistance = maxDistance * std::min(distance, 1.0f);
+
+ m_qnxCamera->setManualFocusStep(qnxDistance);
+}
+
+void QQnxPlatformCamera::zoomTo(float factor, float)
+{
+ if (!m_qnxCamera)
+ return;
+
+ const uint32_t minZoom = m_qnxCamera->minimumZoomLevel();
+ const uint32_t maxZoom = m_qnxCamera->maximumZoomLevel();
+
+ if (maxZoom <= minZoom)
+ return;
+
+ // QNX has an integer based API. Interpolate between the levels according to the factor we get
+ const float max = maxZoomFactor();
+ const float min = minZoomFactor();
+
+ if (max <= min)
+ return;
+
+ factor = qBound(min, factor, max) - min;
+
+ const uint32_t zoom = minZoom
+ + static_cast<uint32_t>(qRound(factor*(maxZoom - minZoom)/(max - min)));
+
+ if (m_qnxCamera->setZoomFactor(zoom))
+ zoomFactorChanged(factor);
+}
+
+void QQnxPlatformCamera::setExposureCompensation(float ev)
+{
+ if (!m_qnxCamera)
+ return;
+
+ m_qnxCamera->setEvOffset(ev);
+}
+
+int QQnxPlatformCamera::isoSensitivity() const
+{
+ if (!m_qnxCamera)
+ return 0;
+
+ return m_qnxCamera->manualIsoSensitivity();
+}
+
+void QQnxPlatformCamera::setManualIsoSensitivity(int value)
+{
+ if (!m_qnxCamera)
+ return;
+
+ const uint32_t isoValue = std::max(0, value);
+
+ m_qnxCamera->setManualIsoSensitivity(isoValue);
+}
+
+void QQnxPlatformCamera::setManualExposureTime(float seconds)
+{
+ if (!m_qnxCamera)
+ return;
+
+ m_qnxCamera->setManualExposureTime(seconds);
+}
+
+float QQnxPlatformCamera::exposureTime() const
+{
+ if (!m_qnxCamera)
+ return 0.0;
+
+ return static_cast<float>(m_qnxCamera->manualExposureTime());
+}
+
+bool QQnxPlatformCamera::isWhiteBalanceModeSupported(QCamera::WhiteBalanceMode mode) const
+{
+ if (m_maxColorTemperature != 0)
+ return true;
+
+ return mode == QCamera::WhiteBalanceAuto;
+}
+
+void QQnxPlatformCamera::setWhiteBalanceMode(QCamera::WhiteBalanceMode mode)
+{
+ if (!m_qnxCamera)
+ return;
+
+ if (mode == QCamera::WhiteBalanceAuto) {
+ m_qnxCamera->setWhiteBalanceMode(CAMERA_WHITEBALANCEMODE_AUTO);
+ } else {
+ m_qnxCamera->setWhiteBalanceMode(CAMERA_WHITEBALANCEMODE_MANUAL);
+ setColorTemperature(colorTemperatureForWhiteBalance(mode));
+ }
+}
+
+void QQnxPlatformCamera::setColorTemperature(int temperature)
+{
+ if (!m_qnxCamera)
+ return;
+
+ const auto normalizedTemp = std::clamp<uint32_t>(std::max(0, temperature),
+ m_minColorTemperature, m_maxColorTemperature);
+
+ if (m_qnxCamera->hasContinuousWhiteBalanceValues()) {
+ m_qnxCamera->setManualWhiteBalance(normalizedTemp);
+ } else {
+ uint32_t delta = std::numeric_limits<uint32_t>::max();
+ uint32_t closestTemp = 0;
+
+ for (uint32_t value : m_qnxCamera->supportedWhiteBalanceValues()) {
+ const auto &[min, max] = std::minmax(value, normalizedTemp);
+ const uint32_t currentDelta = max - min;
+
+ if (currentDelta < delta) {
+ closestTemp = value;
+ delta = currentDelta;
+ }
+ }
+
+ m_qnxCamera->setManualWhiteBalance(closestTemp);
+ }
+}
+
+bool QQnxPlatformCamera::startVideoRecording()
+{
+ if (!m_qnxCamera) {
+ qWarning("QQnxPlatformCamera: cannot start video recording - no no camera assigned");
+ return false;
+ }
+
+ if (!isVideoEncodingSupported()) {
+ qWarning("QQnxPlatformCamera: cannot start video recording - not supported");
+ return false;
+ }
+
+ if (!m_qnxCamera->isActive()) {
+ qWarning("QQnxPlatformCamera: cannot start video recording - camera not started");
+ return false;
+ }
+
+ const QString container = m_encoderSettings.mimeType().preferredSuffix();
+ const QString location = QMediaStorageLocation::generateFileName(m_outputUrl.toLocalFile(),
+ QStandardPaths::MoviesLocation, container);
+
+#if 0
+ {
+ static void *libScreen = nullptr;
+
+ if (!libScreen)
+ libScreen = dlopen("/usr/lib/libscreen.so.1", RTLD_GLOBAL);
+ }
+#endif
+
+ qDebug() << "Recording to" << location;
+ return m_qnxCamera->startVideoRecording(location);
+}
+
+bool QQnxPlatformCamera::isVideoEncodingSupported() const
+{
+ return m_qnxCamera && m_qnxCamera->hasFeature(CAMERA_FEATURE_VIDEO);
+}
+
+void QQnxPlatformCamera::setOutputUrl(const QUrl &url)
+{
+ m_outputUrl = url;
+}
+
+void QQnxPlatformCamera::setMediaEncoderSettings(const QMediaEncoderSettings &settings)
+{
+ m_encoderSettings = settings;
+}
+
+void QQnxPlatformCamera::updateCameraFeatures()
+{
+ if (!m_qnxCamera)
+ return;
+
+ QCamera::Features features = {};
+
+ if (m_qnxCamera->hasFeature(CAMERA_FEATURE_REGIONFOCUS))
+ features |= QCamera::Feature::CustomFocusPoint;
+
+ supportedFeaturesChanged(features);
+
+ minimumZoomFactorChanged(m_qnxCamera->minimumZoomLevel());
+ maximumZoomFactorChanged(m_qnxCamera->maximumZoomLevel());
+
+ const QList<uint32_t> wbValues = m_qnxCamera->supportedWhiteBalanceValues();
+
+ if (wbValues.isEmpty()) {
+ m_minColorTemperature = m_maxColorTemperature = 0;
+ } else {
+ const auto &[minTemp, maxTemp] = std::minmax_element(wbValues.begin(), wbValues.end());
+
+ m_minColorTemperature = *minTemp;
+ m_maxColorTemperature = *maxTemp;
+ }
+}
+
+void QQnxPlatformCamera::onFrameAvailable()
+{
+ if (!m_videoSink)
+ return;
+
+ std::unique_ptr<QQnxCameraFrameBuffer> currentFrame = m_qnxCamera->takeCurrentFrame();
+
+ if (!currentFrame)
+ return;
+
+ const QVideoFrame actualFrame(currentFrame.get(),
+ QVideoFrameFormat(currentFrame->size(), currentFrame->pixelFormat()));
+
+ currentFrame.release(); // QVideoFrame has taken ownership of the internal
+ // buffer
+
+ m_videoSink->setVideoFrame(actualFrame);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/multimedia/qnx/camera/qqnxplatformcamera_p.h b/src/plugins/multimedia/qnx/camera/qqnxplatformcamera_p.h
new file mode 100644
index 000000000..0e16c9cf7
--- /dev/null
+++ b/src/plugins/multimedia/qnx/camera/qqnxplatformcamera_p.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Research In Motion
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QQNXPLATFORMCAMERA_H
+#define QQNXPLATFORMCAMERA_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qqnxcamera_p.h"
+
+#include <private/qplatformcamera_p.h>
+#include <private/qplatformmediarecorder_p.h>
+
+#include <QtCore/qlist.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qurl.h>
+
+#include <memory>
+
+QT_BEGIN_NAMESPACE
+
+class QQnxPlatformCameraFrameBuffer;
+class QQnxMediaCaptureSession;
+class QQnxVideoSink;
+class QQnxCameraFrameBuffer;
+
+class QQnxPlatformCamera : public QPlatformCamera
+{
+ Q_OBJECT
+public:
+ explicit QQnxPlatformCamera(QCamera *parent);
+ ~QQnxPlatformCamera();
+
+ bool isActive() const override;
+ void setActive(bool active) override;
+ void start();
+ void stop();
+
+ void setCamera(const QCameraDevice &camera) override;
+
+ bool setCameraFormat(const QCameraFormat &format) override;
+
+ void setCaptureSession(QPlatformMediaCaptureSession *session) override;
+
+ bool isFocusModeSupported(QCamera::FocusMode mode) const override;
+ void setFocusMode(QCamera::FocusMode mode) override;
+
+ void setCustomFocusPoint(const QPointF &point) override;
+
+ void setFocusDistance(float distance) override;
+
+ void zoomTo(float newZoomFactor, float rate = -1.) override;
+
+ void setExposureCompensation(float ev) override;
+
+ int isoSensitivity() const override;
+ void setManualIsoSensitivity(int value) override;
+ void setManualExposureTime(float seconds) override;
+ float exposureTime() const override;
+
+ bool isWhiteBalanceModeSupported(QCamera::WhiteBalanceMode mode) const override;
+ void setWhiteBalanceMode(QCamera::WhiteBalanceMode mode) override;
+ void setColorTemperature(int temperature) override;
+
+ void setOutputUrl(const QUrl &url);
+ void setMediaEncoderSettings(const QMediaEncoderSettings &settings);
+
+ bool startVideoRecording();
+
+private:
+ void updateCameraFeatures();
+ void setColorTemperatureInternal(unsigned temp);
+
+ bool isVideoEncodingSupported() const;
+
+ void onFrameAvailable();
+
+ QQnxMediaCaptureSession *m_session = nullptr;
+ QQnxVideoSink *m_videoSink = nullptr;
+
+ QCameraDevice m_cameraDevice;
+
+ QUrl m_outputUrl;
+
+ QMediaEncoderSettings m_encoderSettings;
+
+ uint32_t m_minColorTemperature = 0;
+ uint32_t m_maxColorTemperature = 0;
+
+ QMutex m_currentFrameMutex;
+
+ std::unique_ptr<QQnxCamera> m_qnxCamera;
+ std::unique_ptr<QQnxCameraFrameBuffer> m_currentFrame;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/multimedia/qnx/capture/qqnxmediacapturesession.cpp b/src/plugins/multimedia/qnx/capture/qqnxmediacapturesession.cpp
index c38dcfd80..99ca0ab8b 100644
--- a/src/plugins/multimedia/qnx/capture/qqnxmediacapturesession.cpp
+++ b/src/plugins/multimedia/qnx/capture/qqnxmediacapturesession.cpp
@@ -39,7 +39,7 @@
#include "qqnxmediacapturesession_p.h"
#include "qqnxaudioinput_p.h"
-#include "qqnxcamera_p.h"
+#include "qqnxplatformcamera_p.h"
#include "qqnximagecapture_p.h"
#include "qqnxmediarecorder_p.h"
#include "qqnxvideosink_p.h"
@@ -65,7 +65,8 @@ void QQnxMediaCaptureSession::setCamera(QPlatformCamera *camera)
{
if (camera == m_camera)
return;
- m_camera = static_cast<QQnxCamera *>(camera);
+ m_camera = static_cast<QQnxPlatformCamera *>(camera);
+ m_camera->setCaptureSession(this);
emit cameraChanged();
}
diff --git a/src/plugins/multimedia/qnx/capture/qqnxmediacapturesession_p.h b/src/plugins/multimedia/qnx/capture/qqnxmediacapturesession_p.h
index ec15d80ba..7b2f46793 100644
--- a/src/plugins/multimedia/qnx/capture/qqnxmediacapturesession_p.h
+++ b/src/plugins/multimedia/qnx/capture/qqnxmediacapturesession_p.h
@@ -57,7 +57,7 @@
QT_BEGIN_NAMESPACE
class QQnxAudioInput;
-class QQnxCamera;
+class QQnxPlatformCamera;
class QQnxImageCapture;
class QQnxMediaRecorder;
class QQnxVideoSink;
@@ -90,7 +90,7 @@ public:
QQnxVideoSink *videoSink() const;
private:
- QQnxCamera *m_camera = nullptr;
+ QQnxPlatformCamera *m_camera = nullptr;
QQnxImageCapture *m_imageCapture = nullptr;
QQnxMediaRecorder *m_mediaRecorder = nullptr;
QQnxAudioInput *m_audioInput = nullptr;
diff --git a/src/plugins/multimedia/qnx/capture/qqnxmediarecorder.cpp b/src/plugins/multimedia/qnx/capture/qqnxmediarecorder.cpp
index 6aa0c686b..282743dbe 100644
--- a/src/plugins/multimedia/qnx/capture/qqnxmediarecorder.cpp
+++ b/src/plugins/multimedia/qnx/capture/qqnxmediarecorder.cpp
@@ -39,6 +39,7 @@
****************************************************************************/
#include "qqnxmediarecorder_p.h"
+#include "qqnxplatformcamera_p.h"
#include "qqnxaudioinput_p.h"
#include "qqnxcamera_p.h"
#include "qqnxmediacapturesession_p.h"
@@ -118,11 +119,13 @@ void QQnxMediaRecorder::startVideoRecording(QMediaEncoderSettings &settings)
if (!hasCamera())
return;
- auto *camera = static_cast<QQnxCamera*>(m_session->camera());
+ auto *camera = static_cast<QQnxPlatformCamera*>(m_session->camera());
camera->setMediaEncoderSettings(settings);
camera->setOutputUrl(outputLocation());
- camera->start();
+
+ if (camera->startVideoRecording())
+ stateChanged(QMediaRecorder::RecordingState);
}
void QQnxMediaRecorder::stopVideoRecording()
@@ -130,10 +133,11 @@ void QQnxMediaRecorder::stopVideoRecording()
if (!hasCamera())
return;
- auto *camera = static_cast<QQnxCamera*>(m_session->camera());
+ auto *camera = static_cast<QQnxPlatformCamera*>(m_session->camera());
camera->stop();
+ stateChanged(QMediaRecorder::StoppedState);
}
bool QQnxMediaRecorder::hasCamera() const
diff --git a/src/plugins/multimedia/qnx/qqnxmediaintegration.cpp b/src/plugins/multimedia/qnx/qqnxmediaintegration.cpp
index 14d403b64..cbae28160 100644
--- a/src/plugins/multimedia/qnx/qqnxmediaintegration.cpp
+++ b/src/plugins/multimedia/qnx/qqnxmediaintegration.cpp
@@ -44,6 +44,8 @@
#include "qqnxvideodevices_p.h"
#include "qqnxvideosink_p.h"
#include "qqnxmediaplayer_p.h"
+#include "qqnximagecapture_p.h"
+#include "qqnxplatformcamera_p.h"
#include <QtMultimedia/private/qplatformmediaplugin_p.h>
QT_BEGIN_NAMESPACE
@@ -103,6 +105,11 @@ QPlatformMediaRecorder *QQnxMediaIntegration::createRecorder(QMediaRecorder *par
return new QQnxMediaRecorder(parent);
}
+QPlatformCamera *QQnxMediaIntegration::createCamera(QCamera *parent)
+{
+ return new QQnxPlatformCamera(parent);
+}
+
QT_END_NAMESPACE
#include "qqnxmediaintegration.moc"
diff --git a/src/plugins/multimedia/qnx/qqnxmediaintegration_p.h b/src/plugins/multimedia/qnx/qqnxmediaintegration_p.h
index a480841a5..1567fce8f 100644
--- a/src/plugins/multimedia/qnx/qqnxmediaintegration_p.h
+++ b/src/plugins/multimedia/qnx/qqnxmediaintegration_p.h
@@ -74,6 +74,8 @@ public:
QPlatformMediaRecorder *createRecorder(QMediaRecorder *parent) override;
+ QPlatformCamera *createCamera(QCamera *parent) override;
+
QQnxFormatInfo *m_formatInfo = nullptr;
};
diff --git a/src/plugins/multimedia/qnx/qqnxvideodevices.cpp b/src/plugins/multimedia/qnx/qqnxvideodevices.cpp
index 5414990f9..a0bd53833 100644
--- a/src/plugins/multimedia/qnx/qqnxvideodevices.cpp
+++ b/src/plugins/multimedia/qnx/qqnxvideodevices.cpp
@@ -38,14 +38,15 @@
****************************************************************************/
#include "qqnxvideodevices_p.h"
+#include "qqnxcamera_p.h"
#include "private/qcameradevice_p.h"
#include "qcameradevice.h"
-#include <camera/camera_api.h>
-
#include <qdir.h>
#include <qdebug.h>
+#include <optional>
+
QT_BEGIN_NAMESPACE
static QVideoFrameFormat::PixelFormat fromCameraFrametype(camera_frametype_t type)
@@ -71,77 +72,51 @@ static QVideoFrameFormat::PixelFormat fromCameraFrametype(camera_frametype_t typ
}
}
-static QList<QCameraDevice> enumerateCameras()
+static std::optional<QCameraDevice> createCameraDevice(camera_unit_t unit, bool isDefault)
{
+ const QQnxCamera camera(unit);
- camera_unit_t cameraUnits[64];
-
- unsigned int knownCameras = 0;
- const camera_error_t result = camera_get_supported_cameras(64, &knownCameras, cameraUnits);
- if (result != CAMERA_EOK) {
- qWarning() << "Unable to retrieve supported camera types:" << result;
+ if (!camera.isValid()) {
+ qWarning() << "Invalid camera unit:" << unit;
return {};
}
- QList<QCameraDevice> cameras;
- for (unsigned int i = 0; i < knownCameras; ++i) {
- QCameraDevicePrivate *p = new QCameraDevicePrivate;
- p->id = QByteArray::number(cameraUnits[i]);
-
- char name[CAMERA_LOCATION_NAMELEN];
- camera_get_location_property(cameraUnits[i], CAMERA_LOCATION_NAME, &name, CAMERA_LOCATION_END);
- p->description = QString::fromUtf8(name);
-
- if (i == 0)
- p->isDefault = true;
-
- camera_handle_t handle;
- if (camera_open(cameraUnits[i], CAMERA_MODE_PREAD, &handle) == CAMERA_EOK) {
- // query camera properties
-
- uint32_t nResolutions = 0;
- camera_get_supported_vf_resolutions(handle, 0, &nResolutions, nullptr);
- QVarLengthArray<camera_res_t> resolutions(nResolutions);
- camera_get_supported_vf_resolutions(handle, nResolutions, &nResolutions, resolutions.data());
-
- uint32_t nFrameTypes;
- camera_get_supported_vf_frame_types(handle, 0, &nFrameTypes, nullptr);
- QVarLengthArray<camera_frametype_t> frameTypes(nFrameTypes);
- camera_get_supported_vf_frame_types(handle, nFrameTypes, &nFrameTypes, frameTypes.data());
-
- for (auto res : resolutions) {
- QSize resolution(res.width, res.height);
- p->photoResolutions.append(resolution);
-
- for (auto frameType : frameTypes) {
- auto pixelFormat = fromCameraFrametype(frameType);
- if (pixelFormat == QVideoFrameFormat::Format_Invalid)
- continue;
-
- uint32_t nFrameRates;
- camera_get_specified_vf_framerates(handle, frameType, res, 0, &nFrameRates, nullptr, nullptr);
- QVarLengthArray<double> frameRates(nFrameRates);
- bool continuous = false;
- camera_get_specified_vf_framerates(handle, frameType, res, nFrameRates, &nFrameRates, frameRates.data(), &continuous);
-
- QCameraFormatPrivate *f = new QCameraFormatPrivate;
- f->resolution = resolution;
- f->pixelFormat = pixelFormat;
- f->minFrameRate = 1.e10;
- for (auto fr : frameRates) {
- if (fr < f->minFrameRate)
- f->minFrameRate = fr;
- if (fr > f->maxFrameRate)
- f->maxFrameRate = fr;
- }
- p->videoFormats.append(f->create());
- }
+ auto *p = new QCameraDevicePrivate;
+
+ p->id = QByteArray::number(camera.unit());
+ p->description = camera.name();
+ p->isDefault = isDefault;
+
+ const QList<camera_frametype_t> frameTypes = camera.supportedVfFrameTypes();
+
+ for (camera_res_t res : camera.supportedVfResolutions()) {
+ const QSize resolution(res.width, res.height);
+
+ p->photoResolutions.append(resolution);
+
+ for (camera_frametype_t frameType : camera.supportedVfFrameTypes()) {
+ const QVideoFrameFormat::PixelFormat pixelFormat = fromCameraFrametype(frameType);
+
+ if (pixelFormat == QVideoFrameFormat::Format_Invalid)
+ continue;
+
+ auto *f = new QCameraFormatPrivate;
+ p->videoFormats.append(f->create());
+
+ f->resolution = resolution;
+ f->pixelFormat = pixelFormat;
+ f->minFrameRate = 1.e10;
+
+ for (double fr : camera.specifiedVfFrameRates(frameType, res)) {
+ if (fr < f->minFrameRate)
+ f->minFrameRate = fr;
+ if (fr > f->maxFrameRate)
+ f->maxFrameRate = fr;
}
}
-
- cameras.append(p->create());
}
- return cameras;
+
+ return p->create();
}
QQnxVideoDevices::QQnxVideoDevices(QPlatformMediaIntegration *integration)
@@ -151,10 +126,21 @@ QQnxVideoDevices::QQnxVideoDevices(QPlatformMediaIntegration *integration)
QList<QCameraDevice> QQnxVideoDevices::videoDevices() const
{
- if (!camerasChecked) {
- camerasChecked = true;
- cameras = enumerateCameras();
+ QList<QCameraDevice> cameras;
+
+ bool isDefault = true;
+
+ for (const camera_unit_t cameraUnit : QQnxCamera::supportedUnits()) {
+ const std::optional<QCameraDevice> cameraDevice = createCameraDevice(cameraUnit, isDefault);
+
+ if (!cameraDevice)
+ continue;
+
+ cameras.append(*cameraDevice);
+
+ isDefault = false;
}
+
return cameras;
}
diff --git a/src/plugins/multimedia/qnx/qqnxvideodevices_p.h b/src/plugins/multimedia/qnx/qqnxvideodevices_p.h
index 8900319c1..883064217 100644
--- a/src/plugins/multimedia/qnx/qqnxvideodevices_p.h
+++ b/src/plugins/multimedia/qnx/qqnxvideodevices_p.h
@@ -52,20 +52,15 @@
//
#include <private/qplatformvideodevices_p.h>
-#include <qcameradevice.h>
QT_BEGIN_NAMESPACE
class QQnxVideoDevices : public QPlatformVideoDevices
{
public:
- QQnxVideoDevices(QPlatformMediaIntegration *integration);
+ explicit QQnxVideoDevices(QPlatformMediaIntegration *integration);
QList<QCameraDevice> videoDevices() const override;
-
-private:
- mutable bool camerasChecked = false;
- mutable QList<QCameraDevice> cameras;
};
QT_END_NAMESPACE