From 4bcd9000baf27241c52931365c91a42c5ae2f83c Mon Sep 17 00:00:00 2001 From: VaL Doroshchuk Date: Wed, 24 Apr 2019 09:46:42 +0200 Subject: Gstreamer: Don't reset pipeline to GST_STATE_NULL when EndOfStream In case of EOS the state of the pipeline currently is changed to GST_STATE_NULL, which releases some resources and it might take some time to restart the playback. If the media should be played few times, there could be a gap between EOS and new play which can be heard. Suggesting to set the state to GST_STATE_PAUSED instead. If there is a need to release resources, empty QMediaContent should be set to the media player. Change-Id: Ifa5c886abfbea037fd395b7336a5590001d4a7f7 Fixes: QTBUG-75314 Reviewed-by: Andy Shaw --- src/gsttools/qgstreamerplayersession.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gsttools/qgstreamerplayersession.cpp b/src/gsttools/qgstreamerplayersession.cpp index 9858f61c9..1e099fc89 100644 --- a/src/gsttools/qgstreamerplayersession.cpp +++ b/src/gsttools/qgstreamerplayersession.cpp @@ -1886,7 +1886,7 @@ void QGstreamerPlayerSession::endOfMediaReset() m_renderer->stopRenderer(); flushVideoProbes(); - gst_element_set_state(m_pipeline, GST_STATE_NULL); + gst_element_set_state(m_pipeline, GST_STATE_PAUSED); QMediaPlayer::State oldState = m_state; m_pendingState = m_state = QMediaPlayer::StoppedState; -- cgit v1.2.3 From 02f1420dadfc9b68a31181d60d6dfd6e622ce3e8 Mon Sep 17 00:00:00 2001 From: VaL Doroshchuk Date: Tue, 19 Mar 2019 11:12:03 +0100 Subject: QGraphicsVideoItem: Always use generic painter when no gl paint engine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If eglfs is used, then there is valid current gl context and it has OpenGL shader programs (QGLShaderProgram::hasOpenGLShaderPrograms). This gl context makes QPainterVideoSurface to use QVideoSurfaceGlslPainter instead of QVideoSurfaceGenericPainter. QOpenGLCompositorBackingStore uses QImage as a QPaintDevice. In this case QPainter::beginNativePainting does nothing because of QRasterPaintEngine. Since QVideoSurfaceGlslPainter is supposed to work with a gl paint engine and not with a raster one, this prevents rendering any video content. To work this around, view->setViewport(new QOpenGLWidget) could be used, where QOpenGL2PaintEngineEx will be taken into account. If platform was not eglfs, QGLContext::currentContext() could be unavailable which made QPainterVideoSurface to use QVideoSurfaceGenericPainter and the video was rendered correctly. QVideoSurfaceGenericPainter should be used when the paint engine is not gl based. Task-number: QTBUG-57836 Change-Id: Id4839facddb2494ec5abf729ea80068eb5e2af1d Reviewed-by: Andy Shaw Reviewed-by: Christian Strømme --- src/multimediawidgets/qgraphicsvideoitem.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/multimediawidgets/qgraphicsvideoitem.cpp b/src/multimediawidgets/qgraphicsvideoitem.cpp index 002fc2cc2..38f5c0e5b 100644 --- a/src/multimediawidgets/qgraphicsvideoitem.cpp +++ b/src/multimediawidgets/qgraphicsvideoitem.cpp @@ -376,11 +376,15 @@ void QGraphicsVideoItem::paint( if (widget) connect(widget, SIGNAL(destroyed()), d->surface, SLOT(viewportDestroyed())); - d->surface->setGLContext(const_cast(QGLContext::currentContext())); - if (d->surface->supportedShaderTypes() & QPainterVideoSurface::GlslShader) { - d->surface->setShaderType(QPainterVideoSurface::GlslShader); - } else { - d->surface->setShaderType(QPainterVideoSurface::FragmentProgramShader); + if (painter->paintEngine()->type() == QPaintEngine::OpenGL + || painter->paintEngine()->type() == QPaintEngine::OpenGL2) + { + d->surface->setGLContext(const_cast(QGLContext::currentContext())); + if (d->surface->supportedShaderTypes() & QPainterVideoSurface::GlslShader) { + d->surface->setShaderType(QPainterVideoSurface::GlslShader); + } else { + d->surface->setShaderType(QPainterVideoSurface::FragmentProgramShader); + } } #endif if (d->rendererControl && d->rendererControl->surface() != d->surface) -- cgit v1.2.3 From b76fcb32d1cc1d87f1943900c2823c02ee85dbb6 Mon Sep 17 00:00:00 2001 From: Val Doroshchuk Date: Wed, 27 Mar 2019 13:46:33 +0100 Subject: Android: Don't open camera if it was already opened MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The application should only have one Camera object active at a time for a particular hardware camera. Since there is no way to determine that the camera has been already opened by the same application, added a fix to prevent opening the camera if it was already opened and not released. Task-number: QTBUG-73582 Change-Id: Ide9ddea0c32489d86a613846ecf2e91ef94a776c Reviewed-by: Christian Strømme --- src/plugins/android/src/wrappers/jni/androidcamera.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/android/src/wrappers/jni/androidcamera.cpp b/src/plugins/android/src/wrappers/jni/androidcamera.cpp index e3afddd59..90af0119a 100644 --- a/src/plugins/android/src/wrappers/jni/androidcamera.cpp +++ b/src/plugins/android/src/wrappers/jni/androidcamera.cpp @@ -832,10 +832,17 @@ AndroidCameraPrivate::~AndroidCameraPrivate() { } +static qint32 s_activeCameras = 0; + bool AndroidCameraPrivate::init(int cameraId) { m_cameraId = cameraId; QJNIEnvironmentPrivate env; + + const bool opened = s_activeCameras & (1 << cameraId); + if (opened) + return false; + m_camera = QJNIObjectPrivate::callStaticObjectMethod("android/hardware/Camera", "open", "(I)Landroid/hardware/Camera;", @@ -854,6 +861,7 @@ bool AndroidCameraPrivate::init(int cameraId) QJNIObjectPrivate params = m_camera.callObjectMethod("getParameters", "()Landroid/hardware/Camera$Parameters;"); m_parameters = QJNIObjectPrivate(params); + s_activeCameras |= 1 << cameraId; return true; } @@ -864,8 +872,10 @@ void AndroidCameraPrivate::release() m_parametersMutex.lock(); m_parameters = QJNIObjectPrivate(); m_parametersMutex.unlock(); - if (m_camera.isValid()) + if (m_camera.isValid()) { m_camera.callMethod("release"); + s_activeCameras &= ~(1 << m_cameraId); + } } bool AndroidCameraPrivate::lock() -- cgit v1.2.3 From 333aecfd4190b067f29332d3a5087530d92d59b3 Mon Sep 17 00:00:00 2001 From: Val Doroshchuk Date: Thu, 28 Mar 2019 15:52:11 +0100 Subject: Android: Allow starting camera without viewfinder available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently it is not able to start camera without viewfinder. For this purpose there is QAndroidCameraDataVideoOutput with SurfaceView in order to be able to start the camera preview. Implemented dummy QAbstractVideoSurface to render to it when no video output is provided before starting the preview. Task-number: QTBUG-73582 Fixes: QTBUG-73237 Change-Id: Ic76d247b5d5352e8539ba61271484e56d3a40fbd Reviewed-by: Christian Strømme --- .../src/mediacapture/qandroidcamerasession.cpp | 43 ++++++++++++++++------ 1 file changed, 32 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp index efcd56580..6a30e5300 100644 --- a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp @@ -45,6 +45,8 @@ #include "qandroidvideooutput.h" #include "qandroidmediavideoprobecontrol.h" #include "qandroidmultimediautils.h" +#include "qandroidcameravideorenderercontrol.h" +#include #include #include #include @@ -415,27 +417,46 @@ QList QAndroidCameraSession::getSupportedPreviewFpsRang return m_camera ? m_camera->getSupportedPreviewFpsRange() : QList(); } +struct NullSurface : QAbstractVideoSurface +{ + NullSurface(QObject *parent = nullptr) : QAbstractVideoSurface(parent) { } + QList supportedPixelFormats( + QAbstractVideoBuffer::HandleType type = QAbstractVideoBuffer::NoHandle) const override + { + QList result; + if (type == QAbstractVideoBuffer::NoHandle) + result << QVideoFrame::Format_NV21; + + return result; + } + + bool present(const QVideoFrame &) { return false; } +}; + bool QAndroidCameraSession::startPreview() { if (!m_camera) return false; - if (!m_videoOutput) { - Q_EMIT error(QCamera::InvalidRequestError, tr("Camera cannot be started without a viewfinder.")); - return false; - } - if (m_previewStarted) return true; - if (!m_videoOutput->isReady()) - return true; // delay starting until the video output is ready + if (m_videoOutput) { + if (!m_videoOutput->isReady()) + return true; // delay starting until the video output is ready - Q_ASSERT(m_videoOutput->surfaceTexture() || m_videoOutput->surfaceHolder()); + Q_ASSERT(m_videoOutput->surfaceTexture() || m_videoOutput->surfaceHolder()); - if ((m_videoOutput->surfaceTexture() && !m_camera->setPreviewTexture(m_videoOutput->surfaceTexture())) - || (m_videoOutput->surfaceHolder() && !m_camera->setPreviewDisplay(m_videoOutput->surfaceHolder()))) - return false; + if ((m_videoOutput->surfaceTexture() && !m_camera->setPreviewTexture(m_videoOutput->surfaceTexture())) + || (m_videoOutput->surfaceHolder() && !m_camera->setPreviewDisplay(m_videoOutput->surfaceHolder()))) + return false; + } else { + auto control = new QAndroidCameraVideoRendererControl(this, this); + control->setSurface(new NullSurface(this)); + qWarning() << "Starting camera without viewfinder available"; + + return true; + } m_status = QCamera::StartingStatus; emit statusChanged(m_status); -- cgit v1.2.3