简体   繁体   English

qml CaptureSession 在 Android 上冻结应用程序

[英]qml CaptureSession freezes app on Android

I have a bug when using CaptureSession on Qt6.4, if I use it in a dynamic component, when I destroy it, the app freezes and I have to kill it.我在 Qt6.4 上使用 CaptureSession 时有一个错误,如果我在动态组件中使用它,当我销毁它时,应用程序会冻结,我必须杀死它。 This problem does not exist when I compile for Desktop.当我为桌面编译时,这个问题不存在。 I tried on Android 11 & 13, the result is the same.我在 Android 11 和 13 上试过,结果是一样的。

Also it was perfectly working with Qt5 when only using VideoOuput & Camera.仅使用 VideoOuput 和 Camera 时,它也能与 Qt5 完美配合。

I wrote a minimal example using a Loader, that creates the freeze.我使用 Loader 编写了一个最小示例,它创建了冻结。 If someone has an idea to fix it:如果有人有修复它的想法:

import QtQuick 6.4
import QtQuick.Window 6.4
import QtQuick.Controls 6.4
import QtMultimedia

ApplicationWindow
{
id: window
visible: true
width: Screen.desktopAvailableWidth
height: Screen.desktopAvailableHeight

Loader {
    id: loader
    anchors.fill: parent
    active: activeBtn.checked
    sourceComponent: Component {
        Item {
            id: item

            Camera {
                id: camera
                active: true
                focusMode: Camera.FocusModeAutoNear
            }

            CaptureSession {
                camera: camera
                videoOutput: videoOutput
            }

            VideoOutput {
                id: videoOutput
                anchors.fill: parent

                fillMode: VideoOutput.Stretch
            }
        }
    }
}


Button {
    id : activeBtn
    text: "Active CAM"
    checkable: true
    anchors {
        right: parent.right
        bottom: parent.bottom
    }
}
}

The app freezes as soon as I unload the component, so when CaptureSession is destroyed.一旦我卸载组件,应用程序就会冻结,因此当 CaptureSession 被销毁时。

I would make sure the Camera is stopped before destroying the Component .我会确保在销毁Component之前停止Camera

In other words, we need to acknowledge on some backends, the camera may be running in a different thread, and, we must make sure we give it sufficient time to terminate the camera and the corresponding VideoOutput preview before forcibly destroying the QML components.换句话说,我们需要在某些后端承认,相机可能在不同的线程中运行,并且,我们必须确保在强行销毁 QML 组件之前给它足够的时间来终止相机和相应的VideoOutput预览。

We can keep your original property binding for starting the camera, ie我们可以保留您的原始属性以启动相机,即

    property bool cameraActive: false
    Loader {
        id: loader
        anchors.fill: parent
        active: activeBtn.checked || cameraActive

So that will create the component as soon as the Button is checked, HOWEVER, during the initialization of the Component , we changed cameraActive = true;因此,一旦选中Button ,就会创建组件,但是,在Component的初始化期间,我们更改了cameraActive = true; so that it prevents the unchecking of the same Button to destroy the component.这样它就可以防止取消选中同一个Button来销毁组件。

                Component.onCompleted: {
                    cameraActive = true;
                }

We use that Button event to stop the Camera with camera.stop() .我们使用该 Button 事件通过camera.stop()停止Camera

                Connections {
                    target: activeBtn
                    function onCheckedChanged() {
                        if (!activeBtn.checked && camera.active) {
                            camera.stop();
                        }
                    }
                }

As soon as we know the Camera has stopped with camera.active === false , then, we change cameraActive = false and that should resume the destruction of your Component .一旦我们知道Camera已停止并camera.active === false ,我们就会更改cameraActive = false ,这应该会恢复您的Component的销毁。

                Camera {
                    id: camera
                    active: true
                    focusMode: Camera.FocusModeAutoNear
                    onActiveChanged: cameraActive = active
                }

Here's your complete code with all of the above changes.这是包含所有上述更改的完整代码。 Note that I haven't been able to fully verify the code below, so, please treat the code as an educational guide only:请注意,我无法完全验证下面的代码,因此,请仅将代码视为教育指南:

import QtQuick 6.4
import QtQuick.Window 6.4
import QtQuick.Controls 6.4
import QtMultimedia

ApplicationWindow
{
    id: window
    visible: true
    width: Screen.desktopAvailableWidth
    height: Screen.desktopAvailableHeight
    property bool cameraActive: false

    Loader {
        id: loader
        anchors.fill: parent
        active: activeBtn.checked || cameraActive
        sourceComponent: Component {
            Item {
                id: item
                
                Camera {
                    id: camera
                    active: true
                    focusMode: Camera.FocusModeAutoNear
                    onActiveChanged: cameraActive = active
                }
                
                CaptureSession {
                    camera: camera
                    videoOutput: videoOutput
                }
                
                VideoOutput {
                    id: videoOutput
                    anchors.fill: parent
                    
                    fillMode: VideoOutput.Stretch
                }

                Connections {
                    target: activeBtn
                    function onCheckedChanged() {
                        if (!activeBtn.checked && camera.active) {
                            camera.stop();
                        }
                    }
                }

                Component.onCompleted: {
                    cameraActive = true;
                }
            }
        }
    }
    
    Button {
        id : activeBtn
        text: "Active CAM"
        checkable: true
        anchors {
            right: parent.right
            bottom: parent.bottom
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM