QML Camera running in Android dies



  • I am developing an app that uses a QML Camera element. The problem is that after taking some photos the camera dies and does not work anymore until I reopen the app. Could anyone help me?

    I tried to use camera.cameraState = Camera.LoadedState before the camera.start() and camera.cameraState = Camera.UnloadedState after the camera.stop(), but it killed my entire app, not just the camera.

    Ps: I have tested it just in Android until now. I am going to see if it happens in iOS too.

    Here is the entire code:

    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    
    #include <QtQml>
    
    #include "processaimagem.h"
    #include "provedorimagem.h"
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        qmlRegisterType<processaImagem>("ProcessaImagemQml", 1, 0, "ProcessaImagem");
    
        QQmlApplicationEngine engine;
    
        provedorImagem *provedorImg = new provedorImagem;
    
        engine.rootContext()->setContextProperty("ProvedorImagem", provedorImg);
    
        engine.addImageProvider("provedor", provedorImg);
    
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
        return app.exec();
    }
    

    main.qml

    import QtQuick 2.4
    import QtQuick.Window 2.2
    import QtQuick.Controls 1.3
    import QtMultimedia 5.4
    
    import ProcessaImagemQml 1.0
    
    Window {
        visible: true
    
        width: 360
        height: 640
    
        maximumHeight: 640
        minimumHeight: 640
    
        maximumWidth: 360
        minimumWidth: 360
    
        title: "Camera Preview Test"
    
        Rectangle {
            id: principal
    
            anchors.fill: parent
    
            ProcessaImagem {
                id: processaImagem
    
                caminhoImagem: camera.caminhoPreview
                caminhoSalvar: camera.caminhoSalvar
                rectRecorte: camera.rectRecorte
                tamanhoImagem: camera.tamanhoImagem
                anguloOrientacaoCamera: camera.orientation
                posicaoCamera: camera.position
    
                onCaminhoImagemChanged: {
                    rectRecorte = cameraView.mapRectToSource(Qt.rect(cameraView.x, cameraView.y, cameraView.width, cameraView.height));
                    tamanhoImagem = Qt.size(cameraView.sourceRect.width, cameraView.sourceRect.height);
                    ProvedorImagem.carregaImagem(processaImagem.carregaImagem());
                }
    
                onCaminhoSalvarChanged: {
                    removeImagemSalva();
                }
            }
    
            Rectangle {
                id: cameraRectangle
    
                width: parent.width
                height: parent.width
    
                anchors.top: parent.top
    
                color: "lightGrey"
    
                visible: true
    
                Camera {
                    id: camera
    
                    property string caminhoPreview: ""
                    property string caminhoSalvar: ""
                    property int numeroImagem: 0
    
                    captureMode: Camera.CaptureStillImage
    
                    imageCapture {
                        onImageCaptured: {
                            camera.caminhoPreview = preview;
    
                            camera.stop();
    
                            imagemPreview.source = "image://provedor/imagemEditada_" + camera.numeroImagem.toString();
    
                            camera.numeroImagem = camera.numeroImagem + 1;
    
                            imagemPreviewRectangle.visible = true;
    
                            cameraRectangle.visible = false;
                        }
    
                        onImageSaved: {
                            camera.caminhoSalvar = path;
                        }
                    }
                }
    
                VideoOutput {
                    id: cameraView
    
                    visible: true
    
                    focus: visible
    
                    anchors.fill: parent
    
                    source: camera
                    orientation: camera.orientation
                    fillMode: VideoOutput.PreserveAspectCrop
                }
            }
    
            Rectangle {
                id: imagemPreviewRectangle
    
                width: parent.width
                height: parent.width
    
                anchors.top: parent.top
    
                color: "lightGrey"
    
                visible: false
    
                Image {
                    id: imagemPreview
    
                    fillMode: Image.PreserveAspectFit
                    
                    anchors.fill: parent
                }
            }
    
            Rectangle {
                id: controleRectangle
    
                width: parent.width
                height: parent.height - cameraRectangle.height
    
                color: "grey"
    
                anchors.top: cameraRectangle.bottom
    
                Button {
                    id: tirarFotoButton
    
                    text: "Tirar foto"
    
                    anchors.left: parent.left
                    anchors.top: parent.top
    
                    onClicked: {
                        camera.imageCapture.capture();
                    }
                }
    
                Button {
                    id: novaFotoButton
    
                    text: "Tirar nova foto"
    
                    anchors.right: parent.right
                    anchors.top: parent.top
    
                    onClicked: {
                        camera.start();
    
                        imagemPreviewRectangle.visible = false;
    
                        cameraRectangle.visible = true;
                    }
                }
            }
        }
    }
    

    processaimagem.h

    #ifndef PROCESSAIMAGEM_H
    #define PROCESSAIMAGEM_H
    
    #include <QObject>
    #include <QImage>
    #include <QQmlEngine>
    #include <QQmlContext>
    #include <QQuickImageProvider>
    #include <QFile>
    
    #include "provedorimagem.h"
    
    class processaImagem : public QObject
    {
        Q_OBJECT
    
        Q_PROPERTY(QString caminhoImagem READ caminhoImagem WRITE setCaminhoImagem NOTIFY caminhoImagemChanged)
        Q_PROPERTY(QString caminhoSalvar READ caminhoSalvar WRITE setCaminhoSalvar NOTIFY caminhoSalvarChanged)
        Q_PROPERTY(QRect rectRecorte READ rectRecorte WRITE setRectRecorte NOTIFY rectRecorteChanged)
        Q_PROPERTY(QSize tamanhoImagem READ tamanhoImagem WRITE setTamanhoImagem NOTIFY tamanhoImagemChanged)
        Q_PROPERTY(int anguloOrientacaoCamera READ anguloOrientacaoCamera WRITE setAnguloOrientacaoCamera NOTIFY anguloOrientacaoCameraChanged)
        Q_PROPERTY(int posicaoCamera READ posicaoCamera WRITE setPosicaoCamera NOTIFY posicaoCameraChanged)
    
    public slots:
        QImage carregaImagem();
        void removeImagemSalva();
    
    public:
        processaImagem(QObject *parent = 0);
    
        QString caminhoImagem() const;
        void setCaminhoImagem(const QString valor);
    
        QString caminhoSalvar() const;
        void setCaminhoSalvar(const QString valor);
    
        QRect rectRecorte() const;
        void setRectRecorte(const QRect valor);
    
        QSize tamanhoImagem() const;
        void setTamanhoImagem(const QSize valor);
    
        int anguloOrientacaoCamera() const;
        void setAnguloOrientacaoCamera(const int valor);
    
        int posicaoCamera() const;
        void setPosicaoCamera(const int valor);
    
    private:
        QString p_caminhoImagem = "";
        QString p_caminhoSalvar = "";
        QRect p_rectRecorte = QRect(0, 0, 0, 0);
        QSize p_tamanhoImagem = QSize(0, 0);
        int p_anguloOrientacaoCamera = 0;
        int p_posicaoCamera = 0;
    
    signals:
        void caminhoImagemChanged();
        void caminhoSalvarChanged();
        void rectRecorteChanged();
        void tamanhoImagemChanged();
        void anguloOrientacaoCameraChanged();
        void posicaoCameraChanged();
    };
    
    #endif // PROCESSAIMAGEM_H
    

    processaimagem.cpp

    #include "processaimagem.h"
    
    #include <QDebug>
    
    processaImagem::processaImagem(QObject *parent)
    {
    
    }
    
    QImage processaImagem::carregaImagem()
    {
        QUrl caminhoImagem(p_caminhoImagem);
        QQmlEngine *engine = QQmlEngine::contextForObject(this)->engine();
        QQmlImageProviderBase *imageProviderBase = engine->imageProvider(caminhoImagem.host());
        QQuickImageProvider *imageProvider = static_cast<QQuickImageProvider*>(imageProviderBase);
    
    
        QSize imageSize;
        QString imageId = caminhoImagem.path().remove(0, 1);
        QImage imagem = imageProvider->requestImage(imageId, &imageSize, imageSize);
    
        if(imagem.isNull())
        {
            qDebug() << "Erro ao carregar a imagem";
            imagem = QImage();
        }
        else
        {
            if((p_anguloOrientacaoCamera == 90) || (p_anguloOrientacaoCamera == 270))
            {
                int larguraImagem = p_tamanhoImagem.width();
                int alturaImagem = p_tamanhoImagem.height();
    
                p_tamanhoImagem.setWidth(alturaImagem);
                p_tamanhoImagem.setHeight(larguraImagem);
    
                int recorteX = p_rectRecorte.x();
                int recorteY = p_rectRecorte.y();
                int recorteLargura = p_rectRecorte.width();
                int recorteAltura = p_rectRecorte.height();
    
                p_rectRecorte.setRect(recorteY, recorteX, recorteAltura, recorteLargura);
    
                if(imagem.size().width() > imagem.size().height())
                {
                    QTransform rotacao;
                    rotacao.rotate(360 - p_anguloOrientacaoCamera);
                    imagem = imagem.transformed(rotacao);
    
                    qDebug() << "Rodou";
                }
            }
    
            if(imagem.width() != p_tamanhoImagem.width())
            {
                imagem = imagem.scaled(p_tamanhoImagem);
            }
    
            imagem = imagem.copy(p_rectRecorte);
        }
    
        return imagem;
    }
    
    void processaImagem::removeImagemSalva()
    {
        QFile::remove(p_caminhoSalvar);
    }
    
    QString processaImagem::caminhoImagem() const
    {
        return p_caminhoImagem;
    }
    
    void processaImagem::setCaminhoImagem(const QString valor)
    {
        if (valor != p_caminhoImagem)
        {
            p_caminhoImagem = valor;
            emit caminhoImagemChanged();
        }
    }
    
    QString processaImagem::caminhoSalvar() const
    {
        return p_caminhoSalvar;
    }
    
    void processaImagem::setCaminhoSalvar(const QString valor)
    {
        if (valor != p_caminhoSalvar)
        {
            p_caminhoSalvar = valor;
            emit caminhoSalvarChanged();
        }
    }
    
    QRect processaImagem::rectRecorte() const
    {
        return p_rectRecorte;
    }
    
    void processaImagem::setRectRecorte(const QRect valor)
    {
        bool alterou = false;
    
        if (valor.x() != p_rectRecorte.x())
        {
            p_rectRecorte.setX(valor.x());
            alterou = true;
        }
    
        if (valor.y() != p_rectRecorte.y())
        {
            p_rectRecorte.setY(valor.y());
            alterou = true;
        }
    
        if (valor.width() != p_rectRecorte.width())
        {
            p_rectRecorte.setWidth(valor.width());
            alterou = true;
        }
    
        if (valor.height() != p_rectRecorte.height())
        {
            p_rectRecorte.setHeight(valor.height());
            alterou = true;
        }
    
        if(alterou)
        {
            emit rectRecorteChanged();
        }
    }
    
    QSize processaImagem::tamanhoImagem() const
    {
        return p_tamanhoImagem;
    }
    
    void processaImagem::setTamanhoImagem(const QSize valor)
    {
        bool alterou = false;
    
        if (valor.width() != p_tamanhoImagem.width())
        {
            p_tamanhoImagem.setWidth(valor.width());
            alterou = true;
        }
    
        if (valor.height() != p_tamanhoImagem.height())
        {
            p_tamanhoImagem.setHeight(valor.height());
            alterou = true;
        }
    
        if(alterou)
        {
            emit tamanhoImagemChanged();
        }
    }
    
    int processaImagem::anguloOrientacaoCamera() const
    {
        return p_anguloOrientacaoCamera;
    }
    
    void processaImagem::setAnguloOrientacaoCamera(const int valor)
    {
        if (valor != p_anguloOrientacaoCamera)
        {
            p_anguloOrientacaoCamera = valor;
            emit anguloOrientacaoCameraChanged();
        }
    }
    
    int processaImagem::posicaoCamera() const
    {
        return p_posicaoCamera;
    }
    
    void processaImagem::setPosicaoCamera(const int valor)
    {
        if (valor != p_posicaoCamera)
        {
            p_posicaoCamera = valor;
            emit posicaoCameraChanged();
        }
    }
    

    provedorimagem.h

    #ifndef PROVEDORIMAGEM_H
    #define PROVEDORIMAGEM_H
    
    #include <QObject>
    #include <QImage>
    #include <QQuickImageProvider>
    
    class provedorImagem : public QObject, public QQuickImageProvider
    {
        Q_OBJECT
    
    public:
        provedorImagem();
    
        QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
    
    public slots:
        void carregaImagem(QImage imagemRecebida);
    
    private:
        QImage imagem;
    };
    
    #endif // PROVEDORIMAGEM_H
    

    provedorimagem.cpp

    #include "provedorimagem.h"
    
    #include <QDebug>
    
    provedorImagem::provedorImagem() : QQuickImageProvider(QQuickImageProvider::Image)
    {
    
    }
    
    QImage provedorImagem::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
    {
        if(imagem.isNull())
        {
            qDebug() << "Erro ao prover a imagem";
        }
    
        return imagem;
    }
    
    void provedorImagem::carregaImagem(QImage imagemRecebida)
    {
        imagem = imagemRecebida;
    }


Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.