diff options
author | Samuel Mira <samuel.mira@qt.io> | 2021-10-20 16:50:48 +0300 |
---|---|---|
committer | Samuel Mira <samuel.mira@qt.io> | 2021-10-21 17:16:21 +0300 |
commit | 3ed3e14a8965f4e231d80480a587c62d556199b7 (patch) | |
tree | 7db5a8ebe25524ab6a180d0c333715e5f94486bf | |
parent | 7a7886307ca2d72c9767aa0f396e49b4e749a06e (diff) |
Fix crashes on qandroidcapturesession
The auto tests in android is missing a surface, and running those
could crashes when trying to record video. This patch is fixing those
crashes
Fixes: QTBUG-97646
Pick-to: 6.2
Change-Id: I69d9e889453ea5c29958dd1369cf1d2079bfa7c4
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
-rw-r--r-- | src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp | 73 |
1 files changed, 46 insertions, 27 deletions
diff --git a/src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp b/src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp index 03eaa1545..5b93a0d20 100644 --- a/src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp +++ b/src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp @@ -135,7 +135,9 @@ void QAndroidCaptureSession::start(QMediaEncoderSettings &settings, const QUrl & setKeepAlive(true); - if (m_cameraSession && !qt_androidRequestCameraPermission()) { + const bool validCameraSession = m_cameraSession && m_cameraSession->camera(); + + if (validCameraSession && !qt_androidRequestCameraPermission()) { emit error(QMediaRecorder::ResourceError, QLatin1String("Camera permission denied.")); setKeepAlive(false); return; @@ -156,7 +158,7 @@ void QAndroidCaptureSession::start(QMediaEncoderSettings &settings, const QUrl & applySettings(settings); // Set audio/video sources - if (m_cameraSession) { + if (validCameraSession) { m_cameraSession->camera()->stopPreviewSynchronous(); m_cameraSession->applyResolution(settings.videoResolution(), false); m_cameraSession->camera()->unlock(); @@ -176,7 +178,7 @@ void QAndroidCaptureSession::start(QMediaEncoderSettings &settings, const QUrl & m_mediaRecorder->setOutputFormat(m_outputFormat); // Set video encoder settings - if (m_cameraSession) { + if (validCameraSession) { m_mediaRecorder->setVideoSize(settings.videoResolution()); m_mediaRecorder->setVideoFrameRate(qRound(settings.videoFrameRate())); m_mediaRecorder->setVideoEncodingBitRate(settings.videoBitRate()); @@ -213,14 +215,18 @@ void QAndroidCaptureSession::start(QMediaEncoderSettings &settings, const QUrl & // is not necessary when the Camera already has a Surface, it doesn't actually work on some // devices. For example on the Samsung Galaxy Tab 2, the camera server dies after prepare() // and start() if MediaRecorder.setPreviewDisplay() is not called. - if (m_cameraSession) { - // When using a SurfaceTexture, we need to pass a new one to the MediaRecorder, not the same - // one that is set on the Camera or it will crash, hence the reset(). - m_cameraSession->videoOutput()->reset(); - if (m_cameraSession->videoOutput()->surfaceTexture()) - m_mediaRecorder->setSurfaceTexture(m_cameraSession->videoOutput()->surfaceTexture()); - else if (m_cameraSession->videoOutput()->surfaceHolder()) - m_mediaRecorder->setSurfaceHolder(m_cameraSession->videoOutput()->surfaceHolder()); + if (validCameraSession) { + + if (m_cameraSession->videoOutput()) { + // When using a SurfaceTexture, we need to pass a new one to the MediaRecorder, not the + // same one that is set on the Camera or it will crash, hence the reset(). + m_cameraSession->videoOutput()->reset(); + if (m_cameraSession->videoOutput()->surfaceTexture()) + m_mediaRecorder->setSurfaceTexture( + m_cameraSession->videoOutput()->surfaceTexture()); + else if (m_cameraSession->videoOutput()->surfaceHolder()) + m_mediaRecorder->setSurfaceHolder(m_cameraSession->videoOutput()->surfaceHolder()); + } m_cameraSession->disableRotation(); } @@ -244,7 +250,7 @@ void QAndroidCaptureSession::start(QMediaEncoderSettings &settings, const QUrl & m_notifyTimer.start(); updateDuration(); - if (m_cameraSession) { + if (validCameraSession) { m_cameraSession->setReadyForCapture(false); // Preview frame callback is cleared when setting up the camera with the media recorder. @@ -363,23 +369,36 @@ void QAndroidCaptureSession::applySettings(QMediaEncoderSettings &settings) void QAndroidCaptureSession::restartViewfinder() { + + setKeepAlive(false); + if (!m_cameraSession) return; - m_cameraSession->camera()->reconnect(); - - // This is not necessary on most devices, but it crashes on some if we don't stop the - // preview and reset the preview display on the camera when recording is over. - m_cameraSession->camera()->stopPreviewSynchronous(); - m_cameraSession->videoOutput()->reset(); - if (m_cameraSession->videoOutput()->surfaceTexture()) - m_cameraSession->camera()->setPreviewTexture(m_cameraSession->videoOutput()->surfaceTexture()); - else if (m_cameraSession->videoOutput()->surfaceHolder()) - m_cameraSession->camera()->setPreviewDisplay(m_cameraSession->videoOutput()->surfaceHolder()); - - m_cameraSession->camera()->startPreview(); - m_cameraSession->setReadyForCapture(true); - m_cameraSession->enableRotation(); - setKeepAlive(false); + + if (m_cameraSession && m_cameraSession->camera()) { + m_cameraSession->camera()->reconnect(); + + // This is not necessary on most devices, but it crashes on some if we don't stop the + // preview and reset the preview display on the camera when recording is over. + m_cameraSession->camera()->stopPreviewSynchronous(); + + if (m_cameraSession->videoOutput()) { + // When using a SurfaceTexture, we need to pass a new one to the MediaRecorder, not the + // same one that is set on the Camera or it will crash, hence the reset(). + m_cameraSession->videoOutput()->reset(); + if (m_cameraSession->videoOutput()->surfaceTexture()) + m_cameraSession->camera()->setPreviewTexture( + m_cameraSession->videoOutput()->surfaceTexture()); + else if (m_cameraSession->videoOutput()->surfaceHolder()) + m_cameraSession->camera()->setPreviewDisplay( + m_cameraSession->videoOutput()->surfaceHolder()); + } + + m_cameraSession->camera()->startPreview(); + m_cameraSession->setReadyForCapture(true); + m_cameraSession->enableRotation(); + } + m_mediaRecorder = nullptr; } |