summaryrefslogtreecommitdiffstats
path: root/src/plugins/multimedia/qnx/camera/qqnxcamera.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/multimedia/qnx/camera/qqnxcamera.cpp')
-rw-r--r--src/plugins/multimedia/qnx/camera/qqnxcamera.cpp720
1 files changed, 467 insertions, 253 deletions
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)