Revision control
Copy as Markdown
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtMultimedia
// CameraHelper inherits from Camera but adds several helper properties.
// - Adds logging functionality to most signals.
// - Properties for list of various values currently supported by the selected camera-device:
// - FocusMode
// - FlashMode
// - TorchMode
// - Feature flags as a list
// - Turning PixelFormat enum into string
// - Turning cameraFormat into string
Camera {
id: myCamera
// Determines if we should clear all properties whenever we change the device.
property bool clearPropertiesUponDeviceChange: false
onActiveChanged: () => {
console.log("Camera.onActiveChanged signal fired: " + active)
}
onCameraDeviceChanged: () => {
console.log("Camera.onCameraDeviceChanged signal fired: " + cameraDevice)
supportedFocusModes = allFocusModes.filter(item => isFocusModeSupported(item))
currentFocusModeIsSupported = isFocusModeSupported(focusMode)
supportedFlashModes = allFlashModes.filter(item => isFlashModeSupported(item))
currentFlashModeIsSupported = isFlashModeSupported(flashMode)
if (clearPropertiesUponDeviceChange) {
zoomFactor = 1
flashMode = Camera.FlashOff
torchMode = Camera.TorchOff
focusDistance = 1
}
}
onErrorOccurred: (error, msg) => {
console.log("Camera.errorOccurred signal fired: " + msg)
}
onCameraFormatChanged: () => {
console.log("Camera.onCameraFormatChanged signal fired: " + cameraFormat)
}
onCustomFocusPointChanged: () => {
console.log(
"Camera.onCustomFocusPointChanged signal fired: " + customFocusPoint)
}
onFocusModeChanged: () => {
console.log(
"Camera.onFocusModeChanged signal fired: " + focusModeToString(focusMode))
}
onFocusDistanceChanged: () => {
console.log(
"Camera.onFocusDistanceChanged signal fired: " + focusDistance.toFixed(2))
}
onExposureModeChanged: () => {
console.log(
"Camera.onExposureModeChanged signal fired: " + exposureMode)
}
onExposureTimeChanged: () => {
console.log(
"Camera.onExposureTimeChanged signal fired: " + exposureTime)
}
onExposureCompensationChanged: () => {
console.log(
"Camera.onExposureCompensationChanged signal fired: " + exposureCompensation)
}
readonly property var allFocusModes: [Camera.FocusModeAuto, Camera.FocusModeManual]
function focusModeToString(mode) {
if (mode === Camera.FocusModeAuto)
return "Auto"
if (mode === Camera.FocusModeManual)
return "Manual"
return "unrecognized focus mode"
}
property var supportedFocusModes: allFocusModes.filter(item => isFocusModeSupported(item))
property bool currentFocusModeIsSupported: isFocusModeSupported(focusMode)
readonly property var allFlashModes: [
Camera.FlashOff,
Camera.FlashOn,
Camera.FlashAuto]
function flashModeToString(mode) {
switch (mode) {
case Camera.FlashOff: return "Off";
case Camera.FlashOn: return "On";
case Camera.FlashAuto: return "Auto";
default: return "Unrecognized flash mode";
}
}
property var supportedFlashModes: allFlashModes.filter(item => isFlashModeSupported(item))
property bool currentFlashModeIsSupported: isFlashModeSupported(flashMode)
readonly property var allTorchModes: [Camera.TorchOff, Camera.TorchOn, Camera.TorchAuto]
property var supportedTorchModes: allTorchModes.filter(item => isTorchModeSupported(item))
function torchModeToString(mode) {
switch (mode) {
case Camera.TorchOff: return "Off"
case Camera.TorchOn: return "On"
case Camera.TorchAuto: return "Auto"
default: return "Unrecognized torch mode"
}
}
readonly property var allFeatureFlags: [
Camera.ColorTemperature,
Camera.CustomFocusPoint,
Camera.ExposureCompensation,
Camera.FocusDistance,
]
property var supportedFeaturesList: allFeatureFlags
.filter(item => supportedFeatures & item)
function featureFlagToString(flag) {
switch (flag) {
case Camera.ColorTemperature: return "ColorTemperature"
case Camera.CustomFocusPoint: return "CustomFocusPoint"
case Camera.ExposureCompensation: return "ExposureCompensation"
case Camera.FocusDistance: return "FocusDistance"
default: return "Unrecognized feature flag"
}
}
function pixelFormatToString(input) {
// TODO: PixelFormat enum is not exposed to QML
switch (input) {
case 13: return "YUV420P"
case 14: return "YUV422P"
case 15: return "YV12"
case 16: return "UYVY"
case 17: return "YUYV"
case 18: return "NV12"
case 19: return "NV21"
case 26: return "P010"
case 27: return "P016"
case 29: return "Jpeg"
case 31: return "YUV420P10"
}
return "Unrecognized pixel format (" + input + ")"
}
function isCameraFormatNull(format): boolean {
// TODO: There is no QML equivalent of checking if a format is null or default-constructed..
// This is a dirty workaround.
return format.resolution.width <= 0
}
function cameraFormatToString(format) {
if (isCameraFormatNull(format))
return "null format"
return ""
+ format.resolution.width
+ "x"
+ format.resolution.height
+ " "
+ pixelFormatToString(format.pixelFormat)
+ " "
+ format.minFrameRate.toFixed(0)
+ "-"
+ format.maxFrameRate.toFixed(0)
}
// Describes how we want to sort two given formats.
function customCameraFormatSortDelegate(a, b) {
if (a.resolution.width !== b.resolution.width) {
return a.resolution.width - b.resolution.width; // Sort by width increasingly
}
if (a.resolution.height !== b.resolution.height) {
return a.resolution.height - b.resolution.height; // Sort by height increasingly
}
return 0;
}
function errorEnumToString(errorEnum) {
switch (errorEnum) {
case Camera.NoError: return "NoError"
case Camera.CameraError: return "CameraError"
}
return "Unrecognized error enum"
}
}