diff options
Diffstat (limited to 'src/multimedia/platform/gstreamer/mediacapture/qgstreamercamera.cpp')
-rw-r--r-- | src/multimedia/platform/gstreamer/mediacapture/qgstreamercamera.cpp | 124 |
1 files changed, 65 insertions, 59 deletions
diff --git a/src/multimedia/platform/gstreamer/mediacapture/qgstreamercamera.cpp b/src/multimedia/platform/gstreamer/mediacapture/qgstreamercamera.cpp index b5ca6c881..1ee0244ef 100644 --- a/src/multimedia/platform/gstreamer/mediacapture/qgstreamercamera.cpp +++ b/src/multimedia/platform/gstreamer/mediacapture/qgstreamercamera.cpp @@ -53,16 +53,16 @@ #include <QtCore/qdebug.h> QGstreamerCamera::QGstreamerCamera(QCamera *camera) - : QPlatformCamera(camera), - gstCameraBin("camerabin") + : QPlatformCamera(camera) { gstCamera = QGstElement("videotestsrc"); + gstCapsFilter = QGstElement("capsfilter", "videoCapsFilter"); gstDecode = QGstElement("identity"); gstVideoConvert = QGstElement("videoconvert", "videoConvert"); gstVideoScale = QGstElement("videoscale", "videoScale"); - gstCameraBin.add(gstCamera, gstDecode, gstVideoConvert, gstVideoScale); - gstCamera.link(gstDecode, gstVideoConvert, gstVideoScale); - + gstCameraBin = QGstBin("camerabin"); + gstCameraBin.add(gstCamera, gstCapsFilter, gstDecode, gstVideoConvert, gstVideoScale); + gstCamera.link(gstCapsFilter, gstDecode, gstVideoConvert, gstVideoScale); gstCameraBin.addGhostPad(gstVideoScale, "src"); } @@ -97,88 +97,94 @@ void QGstreamerCamera::setCamera(const QCameraDevice &camera) { if (m_cameraDevice == camera) return; -// qDebug() << "setCamera" << camera; + qDebug() << "setCamera" << camera; m_cameraDevice = camera; - gstPipeline.beginConfig(); - - Q_ASSERT(!gstCamera.isNull()); - - gstCamera.setStateSync(GST_STATE_NULL); - gstCameraBin.remove(gstCamera); - + QGstElement gstNewCamera; if (camera.isNull()) { - gstCamera = QGstElement("videotestsrc"); + gstNewCamera = QGstElement("videotestsrc"); } else { auto *devices = static_cast<QGstreamerMediaDevices *>(QGstreamerIntegration::instance()->devices()); auto *device = devices->videoDevice(camera.id()); - gstCamera = gst_device_create_element(device, "camerasrc"); + gstNewCamera = gst_device_create_element(device, "camerasrc"); QGstStructure properties = gst_device_get_properties(device); if (properties.name() == "v4l2deviceprovider") m_v4l2Device = QString::fromUtf8(properties["device.path"].toString()); } - gstCameraBin.add(gstCamera); - // set the camera up with a decent format - setCameraFormatInternal({}); + QCameraFormat f = findBestCameraFormat(camera); + auto caps = QGstMutableCaps::fromCameraFormat(f); + auto gstNewDecode = QGstElement(f.pixelFormat() == QVideoFrameFormat::Format_Jpeg ? "jpegdec" : "identity"); + + gstCamera.setStateSync(GST_STATE_NULL); + gstDecode.setStateSync(GST_STATE_NULL); - gstCamera.setState(GST_STATE_PAUSED); + gstCamera.unlink(gstCapsFilter); + gstCapsFilter.unlink(gstDecode); + gstDecode.unlink(gstVideoConvert); - gstPipeline.endConfig(); - gstPipeline.dumpGraph("setCamera"); + gstCameraBin.remove(gstCamera); + gstCameraBin.remove(gstDecode); + + gstCapsFilter.set("caps", caps); + + gstCameraBin.add(gstNewCamera, gstNewDecode); + + gstNewDecode.link(gstVideoConvert); + gstCapsFilter.link(gstNewDecode); + + if (!gstNewCamera.link(gstCapsFilter)) + qWarning() << "linking camera failed" << gstCamera.name() << caps.toString(); + + // Start sending frames once pipeline is linked + // FIXME: put camera to READY state before linking to decoder as in the NULL state it does not know its true caps + gstCapsFilter.syncStateWithParent(); + gstNewDecode.syncStateWithParent(); + gstNewCamera.syncStateWithParent(); + + gstCamera = gstNewCamera; + gstDecode = gstNewDecode; updateCameraProperties(); } -void QGstreamerCamera::setCameraFormatInternal(const QCameraFormat &format) +bool QGstreamerCamera::setCameraFormat(const QCameraFormat &format) { + if (!format.isNull() && !m_cameraDevice.videoFormats().contains(format)) + return false; + + qDebug() << "Set camera format"; + QCameraFormat f = format; if (f.isNull()) f = findBestCameraFormat(m_cameraDevice); - // add jpeg decoder where required - gstDecode.setStateSync(GST_STATE_NULL); - gstCameraBin.remove(gstDecode); + auto caps = QGstMutableCaps::fromCameraFormat(f); - if (f.pixelFormat() == QVideoFrameFormat::Format_Jpeg) { -// qDebug() << " enabling jpeg decoder"; - gstDecode = QGstElement("jpegdec"); - } else { -// qDebug() << " camera delivers raw video"; - gstDecode = QGstElement("identity"); - } - gstCameraBin.add(gstDecode); - gstDecode.link(gstVideoConvert); + auto newGstDecode = QGstElement(f.pixelFormat() == QVideoFrameFormat::Format_Jpeg ? "jpegdec" : "identity"); + gstCameraBin.add(newGstDecode); + newGstDecode.syncStateWithParent(); - auto caps = QGstMutableCaps::fromCameraFormat(f); - if (!caps.isNull()) { - if (!gstCamera.linkFiltered(gstDecode, caps)) - qWarning() << "linking filtered camera to decoder failed" << gstCamera.name() << gstDecode.name() << caps.toString(); - } else { - if (!gstCamera.link(gstDecode)) - qWarning() << "linking camera to decoder failed" << gstCamera.name() << gstDecode.name(); - } -} + gstCamera.staticPad("src").doInIdleProbe([&](){ + gstCamera.unlink(gstCapsFilter); + gstCapsFilter.unlink(gstDecode); + gstDecode.unlink(gstVideoConvert); -bool QGstreamerCamera::setCameraFormat(const QCameraFormat &format) -{ - if (!format.isNull() && !m_cameraDevice.videoFormats().contains(format)) - return false; - gstPipeline.beginConfig(); - setCameraFormatInternal(format); - gstPipeline.endConfig(); - return true; -} + gstCapsFilter.set("caps", caps); -void QGstreamerCamera::setCaptureSession(QPlatformMediaCaptureSession *session) -{ - QGstreamerMediaCapture *captureSession = static_cast<QGstreamerMediaCapture *>(session); - if (m_session == captureSession) - return; + newGstDecode.link(gstVideoConvert); + gstCapsFilter.link(newGstDecode); + if (!gstCamera.link(gstCapsFilter)) + qWarning() << "linking filtered camera to decoder failed" << gstCamera.name() << caps.toString(); + }); - m_session = captureSession; - gstPipeline = m_session ? m_session->pipeline() : QGstPipeline(); + gstDecode.setStateSync(GST_STATE_NULL); + gstCameraBin.remove(gstDecode); + + gstDecode = newGstDecode; + + return true; } void QGstreamerCamera::updateCameraProperties() |