summaryrefslogtreecommitdiffstats
path: root/src/plugins/gstreamer/camerabin/camerabinsession.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/gstreamer/camerabin/camerabinsession.cpp')
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinsession.cpp1587
1 files changed, 0 insertions, 1587 deletions
diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.cpp b/src/plugins/gstreamer/camerabin/camerabinsession.cpp
deleted file mode 100644
index 22f5fb116..000000000
--- a/src/plugins/gstreamer/camerabin/camerabinsession.cpp
+++ /dev/null
@@ -1,1587 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtMultimedia/private/qtmultimediaglobal_p.h>
-#include "camerabinsession.h"
-#include "camerabincontrol.h"
-#include "camerabinrecorder.h"
-#include "camerabincontainer.h"
-#include "camerabinaudioencoder.h"
-#include "camerabinvideoencoder.h"
-#include "camerabinimageencoder.h"
-
-#if QT_CONFIG(gstreamer_photography)
-#include "camerabinexposure.h"
-#include "camerabinflash.h"
-#include "camerabinfocus.h"
-#include "camerabinlocks.h"
-#endif
-
-#include "camerabinzoom.h"
-#include "camerabinimageprocessing.h"
-#include "camerabinviewfindersettings.h"
-
-#include "camerabincapturedestination.h"
-#include "camerabincapturebufferformat.h"
-#include <private/qgstreamerbushelper_p.h>
-#include <private/qgstreamervideorendererinterface_p.h>
-#include <private/qgstutils_p.h>
-#include <qmediarecorder.h>
-#include <qvideosurfaceformat.h>
-
-#if QT_CONFIG(gstreamer_photography)
-#include <gst/interfaces/photography.h>
-#endif
-
-#include <gst/gsttagsetter.h>
-#include <gst/gstversion.h>
-
-#include <QtCore/qdebug.h>
-#include <QCoreApplication>
-#include <QtCore/qmetaobject.h>
-#include <QtGui/qdesktopservices.h>
-
-#include <QtGui/qimage.h>
-#include <QtCore/qdatetime.h>
-
-#include <algorithm>
-
-//#define CAMERABIN_DEBUG 1
-//#define CAMERABIN_DEBUG_DUMP_BIN 1
-#define ENUM_NAME(c,e,v) (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(e)).valueToKey((v)))
-
-#define FILENAME_PROPERTY "location"
-#define MODE_PROPERTY "mode"
-#define MUTE_PROPERTY "mute"
-#define IMAGE_PP_PROPERTY "image-post-processing"
-#define IMAGE_ENCODER_PROPERTY "image-encoder"
-#define VIDEO_PP_PROPERTY "video-post-processing"
-#define VIEWFINDER_SINK_PROPERTY "viewfinder-sink"
-#define CAMERA_SOURCE_PROPERTY "camera-source"
-#define AUDIO_SOURCE_PROPERTY "audio-source"
-#define SUPPORTED_IMAGE_CAPTURE_CAPS_PROPERTY "image-capture-supported-caps"
-#define SUPPORTED_VIDEO_CAPTURE_CAPS_PROPERTY "video-capture-supported-caps"
-#define SUPPORTED_VIEWFINDER_CAPS_PROPERTY "viewfinder-supported-caps"
-#define AUDIO_CAPTURE_CAPS_PROPERTY "audio-capture-caps"
-#define IMAGE_CAPTURE_CAPS_PROPERTY "image-capture-caps"
-#define VIDEO_CAPTURE_CAPS_PROPERTY "video-capture-caps"
-#define VIEWFINDER_CAPS_PROPERTY "viewfinder-caps"
-#define PREVIEW_CAPS_PROPERTY "preview-caps"
-#define POST_PREVIEWS_PROPERTY "post-previews"
-
-
-#define CAPTURE_START "start-capture"
-#define CAPTURE_STOP "stop-capture"
-
-#define FILESINK_BIN_NAME "videobin-filesink"
-
-#define CAMERABIN_IMAGE_MODE 1
-#define CAMERABIN_VIDEO_MODE 2
-
-#define PREVIEW_CAPS_4_3 \
- "video/x-raw-rgb, width = (int) 640, height = (int) 480"
-
-QT_BEGIN_NAMESPACE
-
-CameraBinSession::CameraBinSession(GstElementFactory *sourceFactory, QObject *parent)
- :QObject(parent),
- m_recordingActive(false),
- m_status(QCamera::UnloadedStatus),
- m_pendingState(QCamera::UnloadedState),
- m_muted(false),
- m_busy(false),
- m_captureMode(QCamera::CaptureStillImage),
- m_audioInputFactory(0),
- m_videoInputFactory(0),
- m_viewfinder(0),
- m_viewfinderInterface(0),
-#if QT_CONFIG(gstreamer_photography)
- m_cameraExposureControl(0),
- m_cameraFlashControl(0),
- m_cameraFocusControl(0),
- m_cameraLocksControl(0),
-#endif
- m_cameraSrc(0),
- m_videoSrc(0),
- m_viewfinderElement(0),
- m_sourceFactory(sourceFactory),
- m_viewfinderHasChanged(true),
- m_inputDeviceHasChanged(true),
- m_usingWrapperCameraBinSrc(false),
- m_viewfinderProbe(this),
- m_audioSrc(0),
- m_audioConvert(0),
- m_capsFilter(0),
- m_fileSink(0),
- m_audioEncoder(0),
- m_videoEncoder(0),
- m_muxer(0)
-{
- if (m_sourceFactory)
- gst_object_ref(GST_OBJECT(m_sourceFactory));
- m_camerabin = gst_element_factory_make(QT_GSTREAMER_CAMERABIN_ELEMENT_NAME, "camerabin");
-
- g_signal_connect(G_OBJECT(m_camerabin), "notify::idle", G_CALLBACK(updateBusyStatus), this);
- g_signal_connect(G_OBJECT(m_camerabin), "element-added", G_CALLBACK(elementAdded), this);
- g_signal_connect(G_OBJECT(m_camerabin), "element-removed", G_CALLBACK(elementRemoved), this);
- qt_gst_object_ref_sink(m_camerabin);
-
- m_bus = gst_element_get_bus(m_camerabin);
-
- m_busHelper = new QGstreamerBusHelper(m_bus, this);
- m_busHelper->installMessageFilter(this);
-
- m_cameraControl = new CameraBinControl(this);
- m_audioEncodeControl = new CameraBinAudioEncoder(this);
- m_videoEncodeControl = new CameraBinVideoEncoder(this);
- m_imageEncodeControl = new CameraBinImageEncoder(this);
- m_recorderControl = new CameraBinRecorder(this);
- m_mediaContainerControl = new CameraBinContainer(this);
- m_cameraZoomControl = new CameraBinZoom(this);
- m_imageProcessingControl = new CameraBinImageProcessing(this);
- m_captureDestinationControl = new CameraBinCaptureDestination(this);
- m_captureBufferFormatControl = new CameraBinCaptureBufferFormat(this);
-
- QByteArray envFlags = qgetenv("QT_GSTREAMER_CAMERABIN_FLAGS");
- if (!envFlags.isEmpty())
- g_object_set(G_OBJECT(m_camerabin), "flags", envFlags.toInt(), NULL);
-
- //post image preview in RGB format
- g_object_set(G_OBJECT(m_camerabin), POST_PREVIEWS_PROPERTY, TRUE, NULL);
-
-#if GST_CHECK_VERSION(1,0,0)
- GstCaps *previewCaps = gst_caps_new_simple(
- "video/x-raw",
- "format", G_TYPE_STRING, "RGBx",
- NULL);
-#else
- GstCaps *previewCaps = gst_caps_from_string("video/x-raw-rgb");
-#endif
-
- g_object_set(G_OBJECT(m_camerabin), PREVIEW_CAPS_PROPERTY, previewCaps, NULL);
- gst_caps_unref(previewCaps);
-}
-
-CameraBinSession::~CameraBinSession()
-{
- if (m_camerabin) {
- if (m_viewfinderInterface)
- m_viewfinderInterface->stopRenderer();
-
- gst_element_set_state(m_camerabin, GST_STATE_NULL);
- gst_element_get_state(m_camerabin, NULL, NULL, GST_CLOCK_TIME_NONE);
- gst_object_unref(GST_OBJECT(m_bus));
- gst_object_unref(GST_OBJECT(m_camerabin));
- }
- if (m_viewfinderElement)
- gst_object_unref(GST_OBJECT(m_viewfinderElement));
-
- if (m_sourceFactory)
- gst_object_unref(GST_OBJECT(m_sourceFactory));
-
- if (m_cameraSrc)
- gst_object_unref(GST_OBJECT(m_cameraSrc));
-
- if (m_videoSrc)
- gst_object_unref(GST_OBJECT(m_videoSrc));
-}
-
-#if QT_CONFIG(gstreamer_photography)
-GstPhotography *CameraBinSession::photography()
-{
- if (GST_IS_PHOTOGRAPHY(m_camerabin)) {
- return GST_PHOTOGRAPHY(m_camerabin);
- }
-
- GstElement * const source = buildCameraSource();
-
- if (source && GST_IS_PHOTOGRAPHY(source))
- return GST_PHOTOGRAPHY(source);
-
- return 0;
-}
-
-CameraBinExposure *CameraBinSession::cameraExposureControl()
-{
- if (!m_cameraExposureControl && photography())
- m_cameraExposureControl = new CameraBinExposure(this);
- return m_cameraExposureControl;
-}
-
-CameraBinFlash *CameraBinSession::cameraFlashControl()
-{
- if (!m_cameraFlashControl && photography())
- m_cameraFlashControl = new CameraBinFlash(this);
- return m_cameraFlashControl;
-}
-
-CameraBinFocus *CameraBinSession::cameraFocusControl()
-{
- if (!m_cameraFocusControl && photography())
- m_cameraFocusControl = new CameraBinFocus(this);
- return m_cameraFocusControl;
-}
-
-CameraBinLocks *CameraBinSession::cameraLocksControl()
-{
- if (!m_cameraLocksControl && photography())
- m_cameraLocksControl = new CameraBinLocks(this);
- return m_cameraLocksControl;
-}
-#endif
-
-bool CameraBinSession::setupCameraBin()
-{
- if (!buildCameraSource())
- return false;
-
- if (m_viewfinderHasChanged) {
- if (m_viewfinderElement) {
- GstPad *pad = gst_element_get_static_pad(m_viewfinderElement, "sink");
- m_viewfinderProbe.removeProbeFromPad(pad);
- gst_object_unref(GST_OBJECT(pad));
- gst_object_unref(GST_OBJECT(m_viewfinderElement));
- }
-
- m_viewfinderElement = m_viewfinderInterface ? m_viewfinderInterface->videoSink() : 0;
-#if CAMERABIN_DEBUG
- qDebug() << Q_FUNC_INFO << "Viewfinder changed, reconfigure.";
-#endif
- m_viewfinderHasChanged = false;
- if (!m_viewfinderElement) {
- if (m_pendingState == QCamera::ActiveState)
- qWarning() << "Starting camera without viewfinder available";
- m_viewfinderElement = gst_element_factory_make("fakesink", NULL);
- }
-
- GstPad *pad = gst_element_get_static_pad(m_viewfinderElement, "sink");
- m_viewfinderProbe.addProbeToPad(pad);
- gst_object_unref(GST_OBJECT(pad));
-
- g_object_set(G_OBJECT(m_viewfinderElement), "sync", FALSE, NULL);
- qt_gst_object_ref_sink(GST_OBJECT(m_viewfinderElement));
- gst_element_set_state(m_camerabin, GST_STATE_NULL);
- g_object_set(G_OBJECT(m_camerabin), VIEWFINDER_SINK_PROPERTY, m_viewfinderElement, NULL);
- }
-
- return true;
-}
-
-static GstCaps *resolutionToCaps(const QSize &resolution,
- qreal frameRate = 0.0,
- QVideoFrame::PixelFormat pixelFormat = QVideoFrame::Format_Invalid)
-{
- GstCaps *caps = 0;
- if (pixelFormat == QVideoFrame::Format_Invalid)
- caps = QGstUtils::videoFilterCaps();
- else
- caps = QGstUtils::capsForFormats(QList<QVideoFrame::PixelFormat>() << pixelFormat);
-
- if (!resolution.isEmpty()) {
- gst_caps_set_simple(
- caps,
- "width", G_TYPE_INT, resolution.width(),
- "height", G_TYPE_INT, resolution.height(),
- NULL);
- }
-
- if (frameRate > 0.0) {
- gint numerator;
- gint denominator;
- qt_gst_util_double_to_fraction(frameRate, &numerator, &denominator);
-
- gst_caps_set_simple(
- caps,
- "framerate", GST_TYPE_FRACTION, numerator, denominator,
- NULL);
- }
-
- return caps;
-}
-
-void CameraBinSession::setupCaptureResolution()
-{
- QSize viewfinderResolution = m_viewfinderSettings.resolution();
- qreal viewfinderFrameRate = m_viewfinderSettings.maximumFrameRate();
- QVideoFrame::PixelFormat viewfinderPixelFormat = m_viewfinderSettings.pixelFormat();
- const QSize imageResolution = m_imageEncodeControl->imageSettings().resolution();
- const QSize videoResolution = m_videoEncodeControl->actualVideoSettings().resolution();
-
- // WrapperCameraBinSrc cannot have different caps on its imgsrc, vidsrc and vfsrc pads.
- // If capture resolution is specified, use it also for the viewfinder to avoid caps negotiation
- // to fail.
- if (m_usingWrapperCameraBinSrc) {
- if (viewfinderResolution.isEmpty()) {
- if (m_captureMode == QCamera::CaptureStillImage && !imageResolution.isEmpty())
- viewfinderResolution = imageResolution;
- else if (m_captureMode == QCamera::CaptureVideo && !videoResolution.isEmpty())
- viewfinderResolution = videoResolution;
- }
-
- // Make sure we don't use incompatible frame rate and pixel format with the new resolution
- if (viewfinderResolution != m_viewfinderSettings.resolution() &&
- (!qFuzzyIsNull(viewfinderFrameRate) || viewfinderPixelFormat != QVideoFrame::Format_Invalid)) {
-
- enum {
- Nothing = 0x0,
- OnlyFrameRate = 0x1,
- OnlyPixelFormat = 0x2,
- Both = 0x4
- };
- quint8 found = Nothing;
- auto viewfinderSettings = supportedViewfinderSettings();
- for (int i = 0; i < viewfinderSettings.count() && !(found & Both); ++i) {
- const QCameraViewfinderSettings &s = viewfinderSettings.at(i);
- if (s.resolution() == viewfinderResolution) {
- if ((qFuzzyIsNull(viewfinderFrameRate) || s.maximumFrameRate() == viewfinderFrameRate)
- && (viewfinderPixelFormat == QVideoFrame::Format_Invalid || s.pixelFormat() == viewfinderPixelFormat))
- found |= Both;
- else if (s.maximumFrameRate() == viewfinderFrameRate)
- found |= OnlyFrameRate;
- else if (s.pixelFormat() == viewfinderPixelFormat)
- found |= OnlyPixelFormat;
- }
- }
-
- if (found & Both) {
- // no-op
- } else if (found & OnlyPixelFormat) {
- viewfinderFrameRate = qreal(0);
- } else if (found & OnlyFrameRate) {
- viewfinderPixelFormat = QVideoFrame::Format_Invalid;
- } else {
- viewfinderPixelFormat = QVideoFrame::Format_Invalid;
- viewfinderFrameRate = qreal(0);
- }
- }
- }
-
- GstCaps *caps = resolutionToCaps(imageResolution);
- g_object_set(m_camerabin, IMAGE_CAPTURE_CAPS_PROPERTY, caps, NULL);
- gst_caps_unref(caps);
-
- qreal framerate = m_videoEncodeControl->videoSettings().frameRate();
- caps = resolutionToCaps(videoResolution, framerate);
- g_object_set(m_camerabin, VIDEO_CAPTURE_CAPS_PROPERTY, caps, NULL);
- gst_caps_unref(caps);
-
- caps = resolutionToCaps(viewfinderResolution, viewfinderFrameRate, viewfinderPixelFormat);
- g_object_set(m_camerabin, VIEWFINDER_CAPS_PROPERTY, caps, NULL);
- gst_caps_unref(caps);
-
- // Special case when using mfw_v4lsrc
- if (m_videoSrc && qstrcmp(qt_gst_element_get_factory_name(m_videoSrc), "mfw_v4lsrc") == 0) {
- int capMode = 0;
- if (viewfinderResolution == QSize(320, 240))
- capMode = 1;
- else if (viewfinderResolution == QSize(720, 480))
- capMode = 2;
- else if (viewfinderResolution == QSize(720, 576))
- capMode = 3;
- else if (viewfinderResolution == QSize(1280, 720))
- capMode = 4;
- else if (viewfinderResolution == QSize(1920, 1080))
- capMode = 5;
- g_object_set(G_OBJECT(m_videoSrc), "capture-mode", capMode, NULL);
-
- if (!qFuzzyIsNull(viewfinderFrameRate)) {
- int n, d;
- qt_gst_util_double_to_fraction(viewfinderFrameRate, &n, &d);
- g_object_set(G_OBJECT(m_videoSrc), "fps-n", n, NULL);
- g_object_set(G_OBJECT(m_videoSrc), "fps-d", d, NULL);
- }
- }
-
- if (m_videoEncoder)
- m_videoEncodeControl->applySettings(m_videoEncoder);
-}
-
-void CameraBinSession::setAudioCaptureCaps()
-{
- QAudioEncoderSettings settings = m_audioEncodeControl->audioSettings();
- const int sampleRate = settings.sampleRate();
- const int channelCount = settings.channelCount();
-
- if (sampleRate <= 0 && channelCount <=0)
- return;
-
-#if GST_CHECK_VERSION(1,0,0)
- GstStructure *structure = gst_structure_new_empty(QT_GSTREAMER_RAW_AUDIO_MIME);
-#else
- GstStructure *structure = gst_structure_new(
- QT_GSTREAMER_RAW_AUDIO_MIME,
- "endianness", G_TYPE_INT, 1234,
- "signed", G_TYPE_BOOLEAN, TRUE,
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- NULL);
-#endif
- if (sampleRate > 0)
- gst_structure_set(structure, "rate", G_TYPE_INT, sampleRate, NULL);
- if (channelCount > 0)
- gst_structure_set(structure, "channels", G_TYPE_INT, channelCount, NULL);
-
- GstCaps *caps = gst_caps_new_full(structure, NULL);
- g_object_set(G_OBJECT(m_camerabin), AUDIO_CAPTURE_CAPS_PROPERTY, caps, NULL);
- gst_caps_unref(caps);
-
- if (m_audioEncoder)
- m_audioEncodeControl->applySettings(m_audioEncoder);
-}
-
-GstElement *CameraBinSession::buildCameraSource()
-{
-#if CAMERABIN_DEBUG
- qDebug() << Q_FUNC_INFO;
-#endif
- if (m_inputDevice.isEmpty())
- return nullptr;
-
- if (!m_inputDeviceHasChanged)
- return m_cameraSrc;
-
- m_inputDeviceHasChanged = false;
- m_usingWrapperCameraBinSrc = false;
-
- GstElement *camSrc = 0;
- g_object_get(G_OBJECT(m_camerabin), CAMERA_SOURCE_PROPERTY, &camSrc, NULL);
-
- if (!m_cameraSrc && m_sourceFactory)
- m_cameraSrc = gst_element_factory_create(m_sourceFactory, "camera_source");
-
- // If gstreamer has set a default source use it.
- if (!m_cameraSrc)
- m_cameraSrc = camSrc;
-
- if (m_cameraSrc) {
-#if CAMERABIN_DEBUG
- qDebug() << "set camera device" << m_inputDevice;
-#endif
- m_usingWrapperCameraBinSrc = qstrcmp(qt_gst_element_get_factory_name(m_cameraSrc), "wrappercamerabinsrc") == 0;
-
- if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_cameraSrc), "video-source")) {
- if (!m_videoSrc) {
- /* QT_GSTREAMER_CAMERABIN_VIDEOSRC can be used to set the video source element.
-
- --- Usage
-
- QT_GSTREAMER_CAMERABIN_VIDEOSRC=[drivername=elementname[,drivername2=elementname2 ...],][elementname]
-
- --- Examples
-
- Always use 'somevideosrc':
- QT_GSTREAMER_CAMERABIN_VIDEOSRC="somevideosrc"
-
- Use 'somevideosrc' when the device driver is 'somedriver', otherwise use default:
- QT_GSTREAMER_CAMERABIN_VIDEOSRC="somedriver=somevideosrc"
-
- Use 'somevideosrc' when the device driver is 'somedriver', otherwise use 'somevideosrc2'
- QT_GSTREAMER_CAMERABIN_VIDEOSRC="somedriver=somevideosrc,somevideosrc2"
- */
- const QByteArray envVideoSource = qgetenv("QT_GSTREAMER_CAMERABIN_VIDEOSRC");
-
- if (!envVideoSource.isEmpty()) {
- const QList<QByteArray> sources = envVideoSource.split(',');
- for (const QByteArray &source : sources) {
- QList<QByteArray> keyValue = source.split('=');
- QByteArray name = keyValue.at(0);
- if (keyValue.count() > 1 && keyValue.at(0) == QGstUtils::cameraDriver(m_inputDevice, m_sourceFactory))
- name = keyValue.at(1);
-
- GError *error = NULL;
- GstElement *element = gst_parse_launch(name, &error);
-
- if (error) {
- g_printerr("ERROR: %s: %s\n", name.constData(), GST_STR_NULL(error->message));
- g_clear_error(&error);
- }
- if (element) {
- m_videoSrc = element;
- break;
- }
- }
- } else if (m_videoInputFactory) {
- m_videoSrc = m_videoInputFactory->buildElement();
- }
-
- if (!m_videoSrc)
- m_videoSrc = gst_element_factory_make("v4l2src", "camera_source");
-
- if (!m_videoSrc)
- m_videoSrc = gst_element_factory_make("ksvideosrc", "camera_source");
-
- if (!m_videoSrc)
- m_videoSrc = gst_element_factory_make("avfvideosrc", "camera_source");
-
- if (m_videoSrc)
- g_object_set(G_OBJECT(m_cameraSrc), "video-source", m_videoSrc, NULL);
- }
-
- if (m_videoSrc) {
- if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSrc), "device"))
- g_object_set(G_OBJECT(m_videoSrc), "device", m_inputDevice.toUtf8().constData(), NULL);
-
- if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSrc), "device-path"))
- g_object_set(G_OBJECT(m_videoSrc), "device-path", m_inputDevice.toUtf8().constData(), NULL);
-
- if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSrc), "device-index"))
- g_object_set(G_OBJECT(m_videoSrc), "device-index", m_inputDevice.toInt(), NULL);
- }
- } else if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_cameraSrc), "camera-device")) {
- if (m_inputDevice == QLatin1String("secondary")) {
- g_object_set(G_OBJECT(m_cameraSrc), "camera-device", 1, NULL);
- } else {
- g_object_set(G_OBJECT(m_cameraSrc), "camera-device", 0, NULL);
- }
- }
- }
-
- if (m_cameraSrc != camSrc) {
- g_object_set(G_OBJECT(m_camerabin), CAMERA_SOURCE_PROPERTY, m_cameraSrc, NULL);
- // Unref only if camSrc is not m_cameraSrc to prevent double unrefing.
- if (camSrc)
- gst_object_unref(GST_OBJECT(camSrc));
- }
-
- return m_cameraSrc;
-}
-
-void CameraBinSession::captureImage(int requestId, const QString &fileName)
-{
- const QString actualFileName = m_mediaStorageLocation.generateFileName(fileName,
- QMediaStorageLocation::Pictures,
- QLatin1String("IMG_"),
- QLatin1String("jpg"));
-
- m_requestId = requestId;
-
-#if CAMERABIN_DEBUG
- qDebug() << Q_FUNC_INFO << m_requestId << fileName << "actual file name:" << actualFileName;
-#endif
-
- g_object_set(G_OBJECT(m_camerabin), FILENAME_PROPERTY, actualFileName.toLocal8Bit().constData(), NULL);
-
- g_signal_emit_by_name(G_OBJECT(m_camerabin), CAPTURE_START, NULL);
-
- m_imageFileName = actualFileName;
-}
-
-void CameraBinSession::setCaptureMode(QCamera::CaptureModes mode)
-{
- m_captureMode = mode;
-
- switch (m_captureMode) {
- case QCamera::CaptureStillImage:
- g_object_set(m_camerabin, MODE_PROPERTY, CAMERABIN_IMAGE_MODE, NULL);
- break;
- case QCamera::CaptureVideo:
- g_object_set(m_camerabin, MODE_PROPERTY, CAMERABIN_VIDEO_MODE, NULL);
- break;
- }
-
- m_recorderControl->updateStatus();
-}
-
-QUrl CameraBinSession::outputLocation() const
-{
- //return the location service wrote data to, not one set by user, it can be empty.
- return m_actualSink;
-}
-
-bool CameraBinSession::setOutputLocation(const QUrl& sink)
-{
- if (!sink.isRelative() && !sink.isLocalFile()) {
- qWarning("Output location must be a local file");
- return false;
- }
-
- m_sink = m_actualSink = sink;
- return true;
-}
-
-void CameraBinSession::setDevice(const QString &device)
-{
- if (m_inputDevice != device) {
- m_inputDevice = device;
- m_inputDeviceHasChanged = true;
- }
-}
-
-void CameraBinSession::setAudioInput(QGstreamerElementFactory *audioInput)
-{
- m_audioInputFactory = audioInput;
-}
-
-void CameraBinSession::setVideoInput(QGstreamerElementFactory *videoInput)
-{
- m_videoInputFactory = videoInput;
- m_inputDeviceHasChanged = true;
-}
-
-bool CameraBinSession::isReady() const
-{
- //it's possible to use QCamera without any viewfinder attached
- return !m_viewfinderInterface || m_viewfinderInterface->isReady();
-}
-
-void CameraBinSession::setViewfinder(QObject *viewfinder)
-{
- if (m_viewfinderInterface)
- m_viewfinderInterface->stopRenderer();
-
- m_viewfinderInterface = qobject_cast<QGstreamerVideoRendererInterface*>(viewfinder);
- if (!m_viewfinderInterface)
- viewfinder = 0;
-
- if (m_viewfinder != viewfinder) {
- bool oldReady = isReady();
-
- if (m_viewfinder) {
- disconnect(m_viewfinder, SIGNAL(sinkChanged()),
- this, SLOT(handleViewfinderChange()));
- disconnect(m_viewfinder, SIGNAL(readyChanged(bool)),
- this, SIGNAL(readyChanged(bool)));
-
- m_busHelper->removeMessageFilter(m_viewfinder);
- }
-
- m_viewfinder = viewfinder;
- m_viewfinderHasChanged = true;
-
- if (m_viewfinder) {
- connect(m_viewfinder, SIGNAL(sinkChanged()),
- this, SLOT(handleViewfinderChange()));
- connect(m_viewfinder, SIGNAL(readyChanged(bool)),
- this, SIGNAL(readyChanged(bool)));
-
- m_busHelper->installMessageFilter(m_viewfinder);
- }
-
- emit viewfinderChanged();
- if (oldReady != isReady())
- emit readyChanged(isReady());
- }
-}
-
-static QList<QCameraViewfinderSettings> capsToViewfinderSettings(GstCaps *supportedCaps)
-{
- QList<QCameraViewfinderSettings> settings;
-
- if (!supportedCaps)
- return settings;
-
- supportedCaps = qt_gst_caps_normalize(supportedCaps);
-
- // Convert caps to QCameraViewfinderSettings
- for (uint i = 0; i < gst_caps_get_size(supportedCaps); ++i) {
- const GstStructure *structure = gst_caps_get_structure(supportedCaps, i);
-
- QCameraViewfinderSettings s;
- s.setResolution(QGstUtils::structureResolution(structure));
- s.setPixelFormat(QGstUtils::structurePixelFormat(structure));
- s.setPixelAspectRatio(QGstUtils::structurePixelAspectRatio(structure));
-
- QPair<qreal, qreal> frameRateRange = QGstUtils::structureFrameRateRange(structure);
- s.setMinimumFrameRate(frameRateRange.first);
- s.setMaximumFrameRate(frameRateRange.second);
-
- if (!s.resolution().isEmpty()
- && s.pixelFormat() != QVideoFrame::Format_Invalid
- && !settings.contains(s)) {
- settings.append(s);
- }
- }
-
- gst_caps_unref(supportedCaps);
- return settings;
-}
-
-QList<QCameraViewfinderSettings> CameraBinSession::supportedViewfinderSettings() const
-{
- if (m_status >= QCamera::LoadedStatus && m_supportedViewfinderSettings.isEmpty()) {
- m_supportedViewfinderSettings =
- capsToViewfinderSettings(supportedCaps(QCamera::CaptureViewfinder));
- }
-
- return m_supportedViewfinderSettings;
-}
-
-QCameraViewfinderSettings CameraBinSession::viewfinderSettings() const
-{
- return m_status == QCamera::ActiveStatus ? m_actualViewfinderSettings : m_viewfinderSettings;
-}
-
-void CameraBinSession::ViewfinderProbe::probeCaps(GstCaps *caps)
-{
- QGstreamerVideoProbeControl::probeCaps(caps);
-
- // Update actual viewfinder settings on viewfinder caps change
- const GstStructure *s = gst_caps_get_structure(caps, 0);
- const QPair<qreal, qreal> frameRate = QGstUtils::structureFrameRateRange(s);
- session->m_actualViewfinderSettings.setResolution(QGstUtils::structureResolution(s));
- session->m_actualViewfinderSettings.setMinimumFrameRate(frameRate.first);
- session->m_actualViewfinderSettings.setMaximumFrameRate(frameRate.second);
- session->m_actualViewfinderSettings.setPixelFormat(QGstUtils::structurePixelFormat(s));
- session->m_actualViewfinderSettings.setPixelAspectRatio(QGstUtils::structurePixelAspectRatio(s));
-}
-
-void CameraBinSession::handleViewfinderChange()
-{
- //the viewfinder will be reloaded
- //shortly when the pipeline is started
- m_viewfinderHasChanged = true;
- emit viewfinderChanged();
-}
-
-void CameraBinSession::setStatus(QCamera::Status status)
-{
- if (m_status == status)
- return;
-
- m_status = status;
- emit statusChanged(m_status);
-
- setStateHelper(m_pendingState);
-}
-
-QCamera::Status CameraBinSession::status() const
-{
- return m_status;
-}
-
-QCamera::State CameraBinSession::pendingState() const
-{
- return m_pendingState;
-}
-
-void CameraBinSession::setState(QCamera::State newState)
-{
- if (newState == m_pendingState)
- return;
-
- m_pendingState = newState;
- emit pendingStateChanged(m_pendingState);
-
-#if CAMERABIN_DEBUG
- qDebug() << Q_FUNC_INFO << newState;
-#endif
-
- setStateHelper(newState);
-}
-
-void CameraBinSession::setStateHelper(QCamera::State state)
-{
- switch (state) {
- case QCamera::UnloadedState:
- unload();
- break;
- case QCamera::LoadedState:
- if (m_status == QCamera::ActiveStatus)
- stop();
- else if (m_status == QCamera::UnloadedStatus)
- load();
- break;
- case QCamera::ActiveState:
- // If the viewfinder changed while in the loaded state, we need to reload the pipeline
- if (m_status == QCamera::LoadedStatus && !m_viewfinderHasChanged)
- start();
- else if (m_status == QCamera::UnloadedStatus || m_viewfinderHasChanged)
- load();
- }
-}
-
-void CameraBinSession::setError(int err, const QString &errorString)
-{
- // Emit only first error
- if (m_pendingState == QCamera::UnloadedState)
- return;
-
- setState(QCamera::UnloadedState);
- emit error(err, errorString);
- setStatus(QCamera::UnloadedStatus);
-}
-
-void CameraBinSession::load()
-{
- if (m_status != QCamera::UnloadedStatus && !m_viewfinderHasChanged)
- return;
-
- setStatus(QCamera::LoadingStatus);
-
- gst_element_set_state(m_camerabin, GST_STATE_NULL);
-
- if (!setupCameraBin()) {
- setError(QCamera::CameraError, QStringLiteral("No camera source available"));
- return;
- }
-
- m_recorderControl->applySettings();
-
-#if QT_CONFIG(gstreamer_encodingprofiles)
- GstEncodingContainerProfile *profile = m_recorderControl->videoProfile();
- if (profile) {
- g_object_set (G_OBJECT(m_camerabin),
- "video-profile",
- profile,
- NULL);
- gst_encoding_profile_unref(profile);
- }
-#endif
-
- gst_element_set_state(m_camerabin, GST_STATE_READY);
-}
-
-void CameraBinSession::unload()
-{
- if (m_status == QCamera::UnloadedStatus || m_status == QCamera::UnloadingStatus)
- return;
-
- setStatus(QCamera::UnloadingStatus);
-
- if (m_recordingActive)
- stopVideoRecording();
-
- if (m_viewfinderInterface)
- m_viewfinderInterface->stopRenderer();
-
- gst_element_set_state(m_camerabin, GST_STATE_NULL);
-
- if (m_busy)
- emit busyChanged(m_busy = false);
-
- m_supportedViewfinderSettings.clear();
-
- setStatus(QCamera::UnloadedStatus);
-}
-
-void CameraBinSession::start()
-{
- if (m_status != QCamera::LoadedStatus)
- return;
-
- setStatus(QCamera::StartingStatus);
-
- setAudioCaptureCaps();
-
- setupCaptureResolution();
-
- gst_element_set_state(m_camerabin, GST_STATE_PLAYING);
-}
-
-void CameraBinSession::stop()
-{
- if (m_status != QCamera::ActiveStatus)
- return;
-
- setStatus(QCamera::StoppingStatus);
-
- if (m_recordingActive)
- stopVideoRecording();
-
- if (m_viewfinderInterface)
- m_viewfinderInterface->stopRenderer();
-
- gst_element_set_state(m_camerabin, GST_STATE_READY);
-}
-
-bool CameraBinSession::isBusy() const
-{
- return m_busy;
-}
-
-void CameraBinSession::updateBusyStatus(GObject *o, GParamSpec *p, gpointer d)
-{
- Q_UNUSED(p);
- CameraBinSession *session = reinterpret_cast<CameraBinSession *>(d);
-
- gboolean idle = false;
- g_object_get(o, "idle", &idle, NULL);
- bool busy = !idle;
-
- if (session->m_busy != busy) {
- session->m_busy = busy;
- QMetaObject::invokeMethod(session, "busyChanged",
- Qt::QueuedConnection,
- Q_ARG(bool, busy));
- }
-}
-
-qint64 CameraBinSession::duration() const
-{
- if (m_camerabin) {
- GstElement *fileSink = gst_bin_get_by_name(GST_BIN(m_camerabin), FILESINK_BIN_NAME);
- if (fileSink) {
- GstFormat format = GST_FORMAT_TIME;
- gint64 duration = 0;
- bool ret = qt_gst_element_query_position(fileSink, format, &duration);
- gst_object_unref(GST_OBJECT(fileSink));
- if (ret)
- return duration / 1000000;
- }
- }
-
- return 0;
-}
-
-bool CameraBinSession::isMuted() const
-{
- return m_muted;
-}
-
-void CameraBinSession::setMuted(bool muted)
-{
- if (m_muted != muted) {
- m_muted = muted;
-
- if (m_camerabin)
- g_object_set(G_OBJECT(m_camerabin), MUTE_PROPERTY, m_muted, NULL);
- emit mutedChanged(m_muted);
- }
-}
-
-void CameraBinSession::setCaptureDevice(const QString &deviceName)
-{
- m_captureDevice = deviceName;
-}
-
-void CameraBinSession::setMetaData(const QMap<QByteArray, QVariant> &data)
-{
- m_metaData = data;
-
- if (m_camerabin)
- QGstUtils::setMetaData(m_camerabin, data);
-}
-
-bool CameraBinSession::processSyncMessage(const QGstreamerMessage &message)
-{
- GstMessage* gm = message.rawMessage();
-
- if (gm && GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) {
- const GstStructure *st = gst_message_get_structure(gm);
- const GValue *sampleValue = 0;
- if (m_captureMode == QCamera::CaptureStillImage
- && gst_structure_has_name(st, "preview-image")
-#if GST_CHECK_VERSION(1,0,0)
- && gst_structure_has_field_typed(st, "sample", GST_TYPE_SAMPLE)
- && (sampleValue = gst_structure_get_value(st, "sample"))) {
- GstSample * const sample = gst_value_get_sample(sampleValue);
- GstCaps * const previewCaps = gst_sample_get_caps(sample);
- GstBuffer * const buffer = gst_sample_get_buffer(sample);
-#else
- && gst_structure_has_field_typed(st, "buffer", GST_TYPE_BUFFER)
- && (sampleValue = gst_structure_get_value(st, "buffer"))) {
- GstBuffer * const buffer = gst_value_get_buffer(sampleValue);
-#endif
-
- QImage image;
-#if GST_CHECK_VERSION(1,0,0)
- GstVideoInfo previewInfo;
- if (gst_video_info_from_caps(&previewInfo, previewCaps))
- image = QGstUtils::bufferToImage(buffer, previewInfo);
-#else
- image = QGstUtils::bufferToImage(buffer);
- gst_buffer_unref(buffer);
-#endif
- if (!image.isNull()) {
- static QMetaMethod exposedSignal = QMetaMethod::fromSignal(&CameraBinSession::imageExposed);
- exposedSignal.invoke(this,
- Qt::QueuedConnection,
- Q_ARG(int,m_requestId));
-
- static QMetaMethod capturedSignal = QMetaMethod::fromSignal(&CameraBinSession::imageCaptured);
- capturedSignal.invoke(this,
- Qt::QueuedConnection,
- Q_ARG(int,m_requestId),
- Q_ARG(QImage,image));
- }
- return true;
- }
-#if QT_CONFIG(gstreamer_photography)
- if (gst_structure_has_name(st, GST_PHOTOGRAPHY_AUTOFOCUS_DONE))
- m_cameraFocusControl->handleFocusMessage(gm);
-#endif
- }
-
- return false;
-}
-
-bool CameraBinSession::processBusMessage(const QGstreamerMessage &message)
-{
- GstMessage* gm = message.rawMessage();
-
- if (gm) {
- if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ERROR) {
- GError *err;
- gchar *debug;
- gst_message_parse_error (gm, &err, &debug);
-
- QString message;
-
- if (err && err->message) {
- message = QString::fromUtf8(err->message);
- qWarning() << "CameraBin error:" << message;
-#if CAMERABIN_DEBUG
- qWarning() << QString::fromUtf8(debug);
-#endif
- }
-
- // Only report error messages from camerabin or video source
- if (GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_camerabin)
- || GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_videoSrc)) {
- if (message.isEmpty())
- message = tr("Camera error");
-
- setError(int(QMediaRecorder::ResourceError), message);
- }
-
-#ifdef CAMERABIN_DEBUG_DUMP_BIN
- _gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_camerabin),
- GstDebugGraphDetails(GST_DEBUG_GRAPH_SHOW_ALL /* GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES*/),
- "camerabin_error");
-#endif
-
-
- if (err)
- g_error_free (err);
-
- if (debug)
- g_free (debug);
- }
-
- if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_WARNING) {
- GError *err;
- gchar *debug;
- gst_message_parse_warning (gm, &err, &debug);
-
- if (err && err->message)
- qWarning() << "CameraBin warning:" << QString::fromUtf8(err->message);
-
- if (err)
- g_error_free (err);
- if (debug)
- g_free (debug);
- }
-
- if (GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_camerabin)) {
- switch (GST_MESSAGE_TYPE(gm)) {
- case GST_MESSAGE_DURATION:
- break;
-
- case GST_MESSAGE_STATE_CHANGED:
- {
-
- GstState oldState;
- GstState newState;
- GstState pending;
-
- gst_message_parse_state_changed(gm, &oldState, &newState, &pending);
-
-
-#if CAMERABIN_DEBUG
- QStringList states;
- states << "GST_STATE_VOID_PENDING" << "GST_STATE_NULL" << "GST_STATE_READY" << "GST_STATE_PAUSED" << "GST_STATE_PLAYING";
-
-
- qDebug() << QString("state changed: old: %1 new: %2 pending: %3") \
- .arg(states[oldState]) \
- .arg(states[newState]) \
- .arg(states[pending]);
-#endif
-
-#ifdef CAMERABIN_DEBUG_DUMP_BIN
- _gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_camerabin),
- GstDebugGraphDetails(GST_DEBUG_GRAPH_SHOW_ALL /*GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES*/),
- "camerabin");
-#endif
-
- switch (newState) {
- case GST_STATE_VOID_PENDING:
- case GST_STATE_NULL:
- setStatus(QCamera::UnloadedStatus);
- break;
- case GST_STATE_READY:
- if (oldState == GST_STATE_NULL)
- m_supportedViewfinderSettings.clear();
-
- setMetaData(m_metaData);
- setStatus(QCamera::LoadedStatus);
- break;
- case GST_STATE_PLAYING:
- setStatus(QCamera::ActiveStatus);
- break;
- case GST_STATE_PAUSED:
- default:
- break;
- }
- }
- break;
- default:
- break;
- }
- }
- }
-
- return false;
-}
-
-QGstreamerVideoProbeControl *CameraBinSession::videoProbe()
-{
- return &m_viewfinderProbe;
-}
-
-QString CameraBinSession::currentContainerFormat() const
-{
- if (!m_muxer)
- return QString();
-
- QString format;
-
- if (GstPad *srcPad = gst_element_get_static_pad(m_muxer, "src")) {
- if (GstCaps *caps = qt_gst_pad_get_caps(srcPad)) {
- gchar *capsString = gst_caps_to_string(caps);
- format = QString::fromLatin1(capsString);
- if (capsString)
- g_free(capsString);
- gst_caps_unref(caps);
- }
- gst_object_unref(GST_OBJECT(srcPad));
- }
-
- return format;
-}
-
-void CameraBinSession::recordVideo()
-{
- QString format = currentContainerFormat();
- if (format.isEmpty())
- format = m_mediaContainerControl->actualContainerFormat();
-
- const QString fileName = m_sink.isLocalFile() ? m_sink.toLocalFile() : m_sink.toString();
- const QFileInfo fileInfo(fileName);
- const QString extension = fileInfo.suffix().isEmpty()
- ? QGstUtils::fileExtensionForMimeType(format)
- : fileInfo.suffix();
-
- const QString actualFileName = m_mediaStorageLocation.generateFileName(fileName,
- QMediaStorageLocation::Movies,
- QLatin1String("clip_"),
- extension);
-
- m_recordingActive = true;
- m_actualSink = QUrl::fromLocalFile(actualFileName);
-
- g_object_set(G_OBJECT(m_camerabin), FILENAME_PROPERTY, QFile::encodeName(actualFileName).constData(), NULL);
-
- g_signal_emit_by_name(G_OBJECT(m_camerabin), CAPTURE_START, NULL);
-}
-
-void CameraBinSession::stopVideoRecording()
-{
- m_recordingActive = false;
- g_signal_emit_by_name(G_OBJECT(m_camerabin), CAPTURE_STOP, NULL);
-}
-
-//internal, only used by CameraBinSession::supportedFrameRates.
-//recursively fills the list of framerates res from value data.
-static void readValue(const GValue *value, QList< QPair<int,int> > *res, bool *continuous)
-{
- if (GST_VALUE_HOLDS_FRACTION(value)) {
- int num = gst_value_get_fraction_numerator(value);
- int denum = gst_value_get_fraction_denominator(value);
-
- *res << QPair<int,int>(num, denum);
- } else if (GST_VALUE_HOLDS_FRACTION_RANGE(value)) {
- const GValue *rateValueMin = gst_value_get_fraction_range_min(value);
- const GValue *rateValueMax = gst_value_get_fraction_range_max(value);
-
- if (continuous)
- *continuous = true;
-
- readValue(rateValueMin, res, continuous);
- readValue(rateValueMax, res, continuous);
- } else if (GST_VALUE_HOLDS_LIST(value)) {
- for (uint i=0; i<gst_value_list_get_size(value); i++) {
- readValue(gst_value_list_get_value(value, i), res, continuous);
- }
- }
-}
-
-static bool rateLessThan(const QPair<int,int> &r1, const QPair<int,int> &r2)
-{
- return r1.first*r2.second < r2.first*r1.second;
-}
-
-GstCaps *CameraBinSession::supportedCaps(QCamera::CaptureModes mode) const
-{
- GstCaps *supportedCaps = 0;
-
- // When using wrappercamerabinsrc, get the supported caps directly from the video source element.
- // This makes sure we only get the caps actually supported by the video source element.
- if (m_videoSrc) {
- GstPad *pad = gst_element_get_static_pad(m_videoSrc, "src");
- if (pad) {
- supportedCaps = qt_gst_pad_get_caps(pad);
- gst_object_unref(GST_OBJECT(pad));
- }
- }
-
- // Otherwise, let the camerabin handle this.
- if (!supportedCaps) {
- const gchar *prop;
- switch (mode) {
- case QCamera::CaptureStillImage:
- prop = SUPPORTED_IMAGE_CAPTURE_CAPS_PROPERTY;
- break;
- case QCamera::CaptureVideo:
- prop = SUPPORTED_VIDEO_CAPTURE_CAPS_PROPERTY;
- break;
- case QCamera::CaptureViewfinder:
- default:
- prop = SUPPORTED_VIEWFINDER_CAPS_PROPERTY;
- break;
- }
-
- g_object_get(G_OBJECT(m_camerabin), prop, &supportedCaps, NULL);
- }
-
- return supportedCaps;
-}
-
-QList< QPair<int,int> > CameraBinSession::supportedFrameRates(const QSize &frameSize, bool *continuous) const
-{
- QList< QPair<int,int> > res;
-
- GstCaps *supportedCaps = this->supportedCaps(QCamera::CaptureVideo);
-
- if (!supportedCaps)
- return res;
-
- GstCaps *caps = 0;
-
- if (frameSize.isEmpty()) {
- caps = gst_caps_copy(supportedCaps);
- } else {
- GstCaps *filter = QGstUtils::videoFilterCaps();
- gst_caps_set_simple(
- filter,
- "width", G_TYPE_INT, frameSize.width(),
- "height", G_TYPE_INT, frameSize.height(),
- NULL);
-
- caps = gst_caps_intersect(supportedCaps, filter);
- gst_caps_unref(filter);
- }
- gst_caps_unref(supportedCaps);
-
- //simplify to the list of rates only:
- caps = gst_caps_make_writable(caps);
- for (uint i=0; i<gst_caps_get_size(caps); i++) {
- GstStructure *structure = gst_caps_get_structure(caps, i);
- gst_structure_set_name(structure, "video/x-raw");
-#if GST_CHECK_VERSION(1,2,0)
- gst_caps_set_features(caps, i, NULL);
-#endif
- const GValue *oldRate = gst_structure_get_value(structure, "framerate");
- if (!oldRate)
- continue;
-
- GValue rate;
- memset(&rate, 0, sizeof(rate));
- g_value_init(&rate, G_VALUE_TYPE(oldRate));
- g_value_copy(oldRate, &rate);
- gst_structure_remove_all_fields(structure);
- gst_structure_set_value(structure, "framerate", &rate);
- g_value_unset(&rate);
- }
-#if GST_CHECK_VERSION(1,0,0)
- caps = gst_caps_simplify(caps);
-#else
- gst_caps_do_simplify(caps);
-#endif
-
- for (uint i=0; i<gst_caps_get_size(caps); i++) {
- GstStructure *structure = gst_caps_get_structure(caps, i);
- const GValue *rateValue = gst_structure_get_value(structure, "framerate");
- if (!rateValue)
- continue;
-
- readValue(rateValue, &res, continuous);
- }
-
- std::sort(res.begin(), res.end(), rateLessThan);
-
-#if CAMERABIN_DEBUG
- qDebug() << "Supported rates:" << caps;
- qDebug() << res;
-#endif
-
- gst_caps_unref(caps);
-
- return res;
-}
-
-//internal, only used by CameraBinSession::supportedResolutions
-//recursively find the supported resolutions range.
-static QPair<int,int> valueRange(const GValue *value, bool *continuous)
-{
- int minValue = 0;
- int maxValue = 0;
-
- if (g_value_type_compatible(G_VALUE_TYPE(value), G_TYPE_INT)) {
- minValue = maxValue = g_value_get_int(value);
- } else if (GST_VALUE_HOLDS_INT_RANGE(value)) {
- minValue = gst_value_get_int_range_min(value);
- maxValue = gst_value_get_int_range_max(value);
- *continuous = true;
- } else if (GST_VALUE_HOLDS_LIST(value)) {
- for (uint i=0; i<gst_value_list_get_size(value); i++) {
- QPair<int,int> res = valueRange(gst_value_list_get_value(value, i), continuous);
-
- if (res.first > 0 && minValue > 0)
- minValue = qMin(minValue, res.first);
- else //select non 0 valid value
- minValue = qMax(minValue, res.first);
-
- maxValue = qMax(maxValue, res.second);
- }
- }
-
- return QPair<int,int>(minValue, maxValue);
-}
-
-static bool resolutionLessThan(const QSize &r1, const QSize &r2)
-{
- return qlonglong(r1.width()) * r1.height() < qlonglong(r2.width()) * r2.height();
-}
-
-
-QList<QSize> CameraBinSession::supportedResolutions(QPair<int,int> rate,
- bool *continuous,
- QCamera::CaptureModes mode) const
-{
- QList<QSize> res;
-
- if (continuous)
- *continuous = false;
-
- GstCaps *supportedCaps = this->supportedCaps(mode);
-
-#if CAMERABIN_DEBUG
- qDebug() << "Source caps:" << supportedCaps;
-#endif
-
- if (!supportedCaps)
- return res;
-
- GstCaps *caps = 0;
- bool isContinuous = false;
-
- if (rate.first <= 0 || rate.second <= 0) {
- caps = gst_caps_copy(supportedCaps);
- } else {
- GstCaps *filter = QGstUtils::videoFilterCaps();
- gst_caps_set_simple(
- filter,
- "framerate" , GST_TYPE_FRACTION , rate.first, rate.second,
- NULL);
- caps = gst_caps_intersect(supportedCaps, filter);
- gst_caps_unref(filter);
- }
- gst_caps_unref(supportedCaps);
-
- //simplify to the list of resolutions only:
- caps = gst_caps_make_writable(caps);
- for (uint i=0; i<gst_caps_get_size(caps); i++) {
- GstStructure *structure = gst_caps_get_structure(caps, i);
- gst_structure_set_name(structure, "video/x-raw");
-#if GST_CHECK_VERSION(1,2,0)
- gst_caps_set_features(caps, i, NULL);
-#endif
- const GValue *oldW = gst_structure_get_value(structure, "width");
- const GValue *oldH = gst_structure_get_value(structure, "height");
- if (!oldW || !oldH)
- continue;
-
- GValue w;
- memset(&w, 0, sizeof(GValue));
- GValue h;
- memset(&h, 0, sizeof(GValue));
- g_value_init(&w, G_VALUE_TYPE(oldW));
- g_value_init(&h, G_VALUE_TYPE(oldH));
- g_value_copy(oldW, &w);
- g_value_copy(oldH, &h);
- gst_structure_remove_all_fields(structure);
- gst_structure_set_value(structure, "width", &w);
- gst_structure_set_value(structure, "height", &h);
- g_value_unset(&w);
- g_value_unset(&h);
- }
-
-#if GST_CHECK_VERSION(1,0,0)
- caps = gst_caps_simplify(caps);
-#else
- gst_caps_do_simplify(caps);
-#endif
-
-
- for (uint i=0; i<gst_caps_get_size(caps); i++) {
- GstStructure *structure = gst_caps_get_structure(caps, i);
- const GValue *wValue = gst_structure_get_value(structure, "width");
- const GValue *hValue = gst_structure_get_value(structure, "height");
- if (!wValue || !hValue)
- continue;
-
- QPair<int,int> wRange = valueRange(wValue, &isContinuous);
- QPair<int,int> hRange = valueRange(hValue, &isContinuous);
-
- QSize minSize(wRange.first, hRange.first);
- QSize maxSize(wRange.second, hRange.second);
-
- if (!minSize.isEmpty())
- res << minSize;
-
- if (minSize != maxSize && !maxSize.isEmpty())
- res << maxSize;
- }
-
-
- std::sort(res.begin(), res.end(), resolutionLessThan);
-
- //if the range is continuos, populate is with the common rates
- if (isContinuous && res.size() >= 2) {
- //fill the ragne with common value
- static const QList<QSize> commonSizes =
- QList<QSize>() << QSize(128, 96)
- << QSize(160,120)
- << QSize(176, 144)
- << QSize(320, 240)
- << QSize(352, 288)
- << QSize(640, 480)
- << QSize(848, 480)
- << QSize(854, 480)
- << QSize(1024, 768)
- << QSize(1280, 720) // HD 720
- << QSize(1280, 1024)
- << QSize(1600, 1200)
- << QSize(1920, 1080) // HD
- << QSize(1920, 1200)
- << QSize(2048, 1536)
- << QSize(2560, 1600)
- << QSize(2580, 1936);
- QSize minSize = res.first();
- QSize maxSize = res.last();
- res.clear();
-
- for (const QSize &candidate : commonSizes) {
- int w = candidate.width();
- int h = candidate.height();
-
- if (w > maxSize.width() && h > maxSize.height())
- break;
-
- if (w >= minSize.width() && h >= minSize.height() &&
- w <= maxSize.width() && h <= maxSize.height())
- res << candidate;
- }
-
- if (res.isEmpty() || res.first() != minSize)
- res.prepend(minSize);
-
- if (res.last() != maxSize)
- res.append(maxSize);
- }
-
-#if CAMERABIN_DEBUG
- qDebug() << "Supported resolutions:" << gst_caps_to_string(caps);
- qDebug() << res;
-#endif
-
- gst_caps_unref(caps);
-
- if (continuous)
- *continuous = isContinuous;
-
- return res;
-}
-
-void CameraBinSession::elementAdded(GstBin *, GstElement *element, CameraBinSession *session)
-{
- GstElementFactory *factory = gst_element_get_factory(element);
-
- if (GST_IS_BIN(element)) {
- g_signal_connect(G_OBJECT(element), "element-added", G_CALLBACK(elementAdded), session);
- g_signal_connect(G_OBJECT(element), "element-removed", G_CALLBACK(elementRemoved), session);
- } else if (!factory) {
- // no-op
-#if GST_CHECK_VERSION(0,10,31)
- } else if (gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER)) {
-#else
- } else if (strstr(gst_element_factory_get_klass(factory), "Encoder/Audio") != NULL) {
-#endif
- session->m_audioEncoder = element;
-
- session->m_audioEncodeControl->applySettings(element);
-#if GST_CHECK_VERSION(0,10,31)
- } else if (gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER)) {
-#else
- } else if (strstr(gst_element_factory_get_klass(factory), "Encoder/Video") != NULL) {
-#endif
- session->m_videoEncoder = element;
-
- session->m_videoEncodeControl->applySettings(element);
-#if GST_CHECK_VERSION(0,10,31)
- } else if (gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_MUXER)) {
-#else
- } else if (strstr(gst_element_factory_get_klass(factory), "Muxer") != NULL) {
-#endif
- session->m_muxer = element;
- }
-}
-
-void CameraBinSession::elementRemoved(GstBin *, GstElement *element, CameraBinSession *session)
-{
- if (element == session->m_audioEncoder)
- session->m_audioEncoder = 0;
- else if (element == session->m_videoEncoder)
- session->m_videoEncoder = 0;
- else if (element == session->m_muxer)
- session->m_muxer = 0;
-}
-
-QT_END_NAMESPACE