crash on iOS with camera
Unsolved
QML and Qt Quick
-
Hi
I have mobile application on which I need to record and send some clip.
Works fine on Android, but on iOS app crashes after I use camera and record some clip.
Page with code, same page does pictures and video, no problem with pictures on Android and iOSimport QtQuick 2.12 import Felgo 3.0 import QtMultimedia 5.12 import QtQuick.Controls 2.12 as QtControls import Qt.labs.platform 1.1 import "../constants" import "../components" import "../utility/utils.js" as Utils Page { id: root title: "New Page" navigationBarHidden: true backgroundColor: "black" property color statusBarColor: "black" property int statusBarTheme property Page returnPage signal closeClicked() onPushed: { cameraLoader.sourceComponent = cameraComponent } onPopped: { cameraLoader.item.stop() cameraLoader.sourceComponent = undefined } Component{ id: cameraComponent Camera{ captureMode: Camera.CaptureStillImage exposure.exposureMode: Camera.ExposurePortrait position: Camera.BackFace flash.mode: Camera.FlashOff focus{ focusMode: Camera.FocusContinuous focusPointMode: Camera.FocusPointCenter } videoRecorder.outputLocation: StandardPaths.writableLocation(StandardPaths.AppDataLocation) } } Loader{ id: cameraLoader onLoaded: { if(item !== undefined) item.start() } } VideoOutput{ id: cameraOutput source: cameraLoader.item anchors.top: parent.top anchors.topMargin: dp(20) anchors.horizontalCenter: parent.horizontalCenter width: parent.width height: 0.82 * parent.height autoOrientation: true Rectangle{ id: topGradientRect anchors.top: parent.top width: parent.width height: 0.1 * parent.height anchors.horizontalCenter: parent.horizontalCenter radius: dp(4) opacity: 0.75 gradient: Gradient{ GradientStop{ position: 0.0 color: Qt.rgba(0, 0, 0, 1) } GradientStop{ position: 1.0 color: Qt.rgba(0, 0, 0, 0) } } } ColorableImage{ id: closeButtonImage anchors.top: parent.top anchors.topMargin: dp(20) anchors.left: parent.left anchors.leftMargin: dp(15) width: dp(24) height: dp(24) imageSource: "qrc:/assets/ic_controls_24_navigation_arrows_collapse_element.svg" imageColor: "white" z: 2 MouseArea{ anchors.fill: parent anchors.margins: -dp(5) onClicked: { closeClicked() } } } Rectangle{ id: bottomGradientRect anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter height: 0.1 * parent.height radius: dp(4) opacity: 0.75 width: parent.width gradient: Gradient{ GradientStop{ position: 0.0 color: Qt.rgba(0, 0, 0, 0) } GradientStop{ position: 1.0 color: Qt.rgba(0, 0, 0, 1) } } } Image{ id: cameraChangeImage anchors.verticalCenter: closeButtonImage.verticalCenter anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenterOffset: -(sourceSize.width/2 + dp(12)) source: "qrc:/assets/icActions24CameraChange.svg" sourceSize: Qt.size(dp(24), dp(24)) MouseArea{ anchors.fill: parent anchors.margins: -dp(5) onClicked: { cameraLoader.item.position = (cameraLoader.item.position === Camera.FrontFace) ? Camera.BackFace : Camera.FrontFace } } } Image{ id: flashOffImage anchors.verticalCenter: closeButtonImage.verticalCenter anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenterOffset: -(cameraChangeImage.anchors.horizontalCenterOffset) source: "qrc:/assets/icActions24FlashOff.svg" sourceSize: Qt.size(dp(24), dp(24)) MouseArea{ anchors.fill: parent anchors.margins: -dp(5) onClicked: { cameraLoader.item.flash.mode = cameraLoader.item.flash.mode === Camera.FlashOn ? Camera.FlashOff : Camera.FlashOn } } } Text { id: currentRecordingDuration visible: videoButton.checked anchors.verticalCenter: flashOffImage.verticalCenter anchors.right: parent.right anchors.rightMargin: dp(20) text: getDurationString(Math.floor(cameraLoader.item !== null ? cameraLoader.item.videoRecorder.duration/1000 : 0)) font.bold: true color: if(cameraLoader.item !== null) cameraLoader.item.videoRecorder.recorderState === CameraRecorder.StoppedState ? "white" : Style.appYellow font.pixelSize: sp(14) } } Rectangle{ id: horizontalDivider anchors.horizontalCenter: parent.horizontalCenter visible: false } QtControls.Button{ id: photoButton text: qsTr("Photo") anchors.bottom: cameraOutput.bottom anchors.bottomMargin: dp(14) anchors.right: horizontalDivider.left anchors.rightMargin: dp(10) padding: 0 checkable: true checked: true width: implicitWidth height: implicitHeight background: Rectangle{ color: "transparent" } contentItem: Text{ text: parent.text color: parent.checked ? Style.appYellow : "white" horizontalAlignment: Qt.AlignHCenter verticalAlignment: Qt.AlignVCenter font.pixelSize: sp(14) font.bold: true } onCheckedChanged:{ if(checked){ cameraLoader.item.captureMode = Camera.CaptureStillImage } } } QtControls.Button{ id: videoButton text: qsTr("Video") anchors.bottom: photoButton.bottom anchors.left: horizontalDivider.right anchors.leftMargin: dp(10) padding: 0 checkable: true width: implicitWidth height: implicitHeight background: Rectangle{ color: "transparent" } contentItem: Text{ text: parent.text color: parent.checked ? Style.appYellow : "white" horizontalAlignment: Qt.AlignHCenter verticalAlignment: Qt.AlignVCenter font.pixelSize: sp(14) font.bold: true } onCheckedChanged: { if(checked){ cameraLoader.item.captureMode = Camera.CaptureVideo } } } QtControls.ButtonGroup{ buttons: [photoButton, videoButton] } Rectangle{ anchors.bottom: photoButton.top anchors.bottomMargin: dp(15) anchors.horizontalCenter: parent.horizontalCenter width: dp(70) height: width radius: height/2 color: Qt.rgba(1, 1, 1, 0.3) Rectangle{ anchors.fill: parent anchors.margins: dp(10) radius: height/2 color: videoButton.checked ? Style.critical : "white" } MouseArea{ anchors.fill: parent onClicked: { if(videoButton.checked){ if(cameraLoader.item.videoRecorder.recorderState === CameraRecorder.StoppedState) cameraLoader.item.videoRecorder.record() else{ cameraLoader.item.videoRecorder.stop() addImageAndBack(cameraLoader.item.videoRecorder.actualLocation, true, true) } }else if(photoButton.checked){ cameraLoader.item.searchAndLock() captureTimer.start() } } } Timer{ id: captureTimer running: false repeat: false interval: 400 onTriggered: { if(cameraLoader.item.imageCapture.ready){ cameraLoader.item.imageCapture.capture() cameraLoader.item.unlock() }else{ start() } } } } Rectangle{ anchors.fill: cameraOutput radius: dp(4) color: "transparent" } Connections{ target: cameraLoader.item.imageCapture enabled: cameraLoader.status === Loader.Ready onCaptureFailed:{ NativeDialog.confirm(qsTr("Error"), message, ok => {}, false) } onImageSaved:{ console.debug(path) //cameraLoader.item.stop() addImageAndBack("file:" + path, false, true) } } function getDurationString(seconds){ const fullMinutes = Math.floor(seconds/60) const secondsInActualMinute = seconds % 60 return `${Utils.makeDoubleDigitString(fullMinutes)}:${Utils.makeDoubleDigitString(secondsInActualMinute)}` } }
Crash is alway a few seconds after I record clip
Thread 26 Queue : com.apple.root.default-qos (concurrent) #0 0x000000019e8b21e0 in objc_msgSend () #1 0x0000000103474d54 in __27-[AVFMediaAssetWriter stop]_block_invoke_3 () #2 0x000000018b159de8 in __111+[__NSOperationInternalObserver _observeValueForKeyPath:ofObject:changeKind:oldValue:newValue:indexes:context:]_block_invoke_2 () #3 0x000000010716c0b4 in _dispatch_call_block_and_release () #4 0x000000010716dde0 in _dispatch_client_callout () #5 0x0000000107170918 in _dispatch_queue_override_invoke () #6 0x0000000107181e30 in _dispatch_root_queue_drain () #7 0x00000001071827ec in _dispatch_worker_thread2 () #8 0x00000001d5a3e768 in _pthread_wqthread ()
I have changed
videoRecorder.outputLocation: StandardPaths.writableLocation(StandardPaths.AppDataLocation)
To different paths but it does not make any difference.
When I leave this unset then
videoRecorder.outputLocation
is empty on iOS, and on Android it has value
Im using Qt 5.15.2 with Felgo.
Any idea what causing the problem?Best Regards
Marek