DirectShow: Refactor camera backend.
Almost entire rewrite of the camera backend. It doesn't provide new features but is more stable and behave as it should. - Correctly report camera state and status - Correctly report if the camera is ready to capture - Emit imageExposed() signal - Save captured images in an appropriate directory - Images can be captured even without a viewport - Better error handling Removed the custom QVideoWidgetControl as it doesn't provide anything more than the QVideoWidget's renderer control fallback. Task-number: QTBUG-33782 Change-Id: I9baf6f83e7c69619f20a101921f7865a1c90d5e4 Reviewed-by: Christian Stromme <christian.stromme@digia.com>
This commit is contained in:
@@ -23,10 +23,5 @@ SOURCES += \
|
||||
$$PWD/dsimagecapturecontrol.cpp \
|
||||
$$PWD/dscamerasession.cpp
|
||||
|
||||
qtHaveModule(widgets) {
|
||||
HEADERS += $$PWD/dsvideowidgetcontrol.h
|
||||
SOURCES += $$PWD/dsvideowidgetcontrol.cpp
|
||||
}
|
||||
|
||||
*-msvc*:INCLUDEPATH += $$(DXSDK_DIR)/include
|
||||
LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32
|
||||
|
||||
@@ -48,10 +48,13 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
DSCameraControl::DSCameraControl(QObject *parent)
|
||||
:QCameraControl(parent), m_captureMode(QCamera::CaptureStillImage)
|
||||
: QCameraControl(parent)
|
||||
, m_state(QCamera::UnloadedState)
|
||||
, m_captureMode(QCamera::CaptureStillImage)
|
||||
{
|
||||
m_session = qobject_cast<DSCameraSession*>(parent);
|
||||
connect(m_session, SIGNAL(stateChanged(QCamera::State)),this, SIGNAL(stateChanged(QCamera::State)));
|
||||
connect(m_session, SIGNAL(statusChanged(QCamera::Status)),
|
||||
this, SIGNAL(statusChanged(QCamera::Status)));
|
||||
}
|
||||
|
||||
DSCameraControl::~DSCameraControl()
|
||||
@@ -60,14 +63,30 @@ DSCameraControl::~DSCameraControl()
|
||||
|
||||
void DSCameraControl::setState(QCamera::State state)
|
||||
{
|
||||
if (m_state == state)
|
||||
return;
|
||||
|
||||
bool succeeded = false;
|
||||
switch (state) {
|
||||
case QCamera::ActiveState:
|
||||
start();
|
||||
break;
|
||||
case QCamera::UnloadedState: /* fall through */
|
||||
case QCamera::LoadedState:
|
||||
stop();
|
||||
break;
|
||||
case QCamera::UnloadedState:
|
||||
succeeded = m_session->unload();
|
||||
break;
|
||||
case QCamera::LoadedState:
|
||||
case QCamera::ActiveState:
|
||||
if (m_state == QCamera::UnloadedState && !m_session->load())
|
||||
return;
|
||||
|
||||
if (state == QCamera::ActiveState)
|
||||
succeeded = m_session->startPreview();
|
||||
else
|
||||
succeeded = m_session->stopPreview();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (succeeded) {
|
||||
m_state = state;
|
||||
emit stateChanged(m_state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,19 +104,17 @@ bool DSCameraControl::isCaptureModeSupported(QCamera::CaptureModes mode) const
|
||||
return bCaptureSupported;
|
||||
}
|
||||
|
||||
void DSCameraControl::start()
|
||||
void DSCameraControl::setCaptureMode(QCamera::CaptureModes mode)
|
||||
{
|
||||
m_session->record();
|
||||
if (m_captureMode != mode && isCaptureModeSupported(mode)) {
|
||||
m_captureMode = mode;
|
||||
emit captureModeChanged(mode);
|
||||
}
|
||||
}
|
||||
|
||||
void DSCameraControl::stop()
|
||||
QCamera::Status DSCameraControl::status() const
|
||||
{
|
||||
m_session->stop();
|
||||
}
|
||||
|
||||
QCamera::State DSCameraControl::state() const
|
||||
{
|
||||
return (QCamera::State)m_session->state();
|
||||
return m_session->status();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -58,28 +58,21 @@ public:
|
||||
DSCameraControl(QObject *parent = 0);
|
||||
~DSCameraControl();
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
QCamera::State state() const;
|
||||
QCamera::State state() const { return m_state; }
|
||||
|
||||
QCamera::CaptureModes captureMode() const { return m_captureMode; }
|
||||
void setCaptureMode(QCamera::CaptureModes mode)
|
||||
{
|
||||
if (m_captureMode != mode) {
|
||||
m_captureMode = mode;
|
||||
emit captureModeChanged(mode);
|
||||
}
|
||||
}
|
||||
void setCaptureMode(QCamera::CaptureModes mode);
|
||||
|
||||
void setState(QCamera::State state);
|
||||
|
||||
QCamera::Status status() const { return QCamera::UnavailableStatus; }
|
||||
QCamera::Status status() const;
|
||||
bool isCaptureModeSupported(QCamera::CaptureModes mode) const;
|
||||
bool canChangeProperty(PropertyChangeType /* changeType */, QCamera::Status /* status */) const {return false; }
|
||||
|
||||
private:
|
||||
DSCameraSession *m_session;
|
||||
DSCameraService *m_service;
|
||||
QCamera::State m_state;
|
||||
QCamera::CaptureModes m_captureMode;
|
||||
};
|
||||
|
||||
|
||||
@@ -42,11 +42,6 @@
|
||||
#include <QtCore/qvariant.h>
|
||||
#include <QtCore/qdebug.h>
|
||||
|
||||
#if defined(HAVE_WIDGETS)
|
||||
#include <QtWidgets/qwidget.h>
|
||||
#include <QVideoWidgetControl>
|
||||
#endif
|
||||
|
||||
#include "dscameraservice.h"
|
||||
#include "dscameracontrol.h"
|
||||
#include "dscamerasession.h"
|
||||
@@ -54,28 +49,16 @@
|
||||
#include "dsvideodevicecontrol.h"
|
||||
#include "dsimagecapturecontrol.h"
|
||||
|
||||
#if defined(HAVE_WIDGETS)
|
||||
#include "dsvideowidgetcontrol.h"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
DSCameraService::DSCameraService(QObject *parent):
|
||||
QMediaService(parent)
|
||||
#if defined(HAVE_WIDGETS)
|
||||
, m_viewFinderWidget(0)
|
||||
#endif
|
||||
, m_videoRenderer(0)
|
||||
{
|
||||
m_session = new DSCameraSession(this);
|
||||
|
||||
m_control = new DSCameraControl(m_session);
|
||||
|
||||
m_videoDevice = new DSVideoDeviceControl(m_session);
|
||||
|
||||
m_imageCapture = new DSImageCaptureControl(m_session);
|
||||
|
||||
m_device = QByteArray("default");
|
||||
}
|
||||
|
||||
DSCameraService::~DSCameraService()
|
||||
@@ -84,9 +67,6 @@ DSCameraService::~DSCameraService()
|
||||
delete m_videoDevice;
|
||||
delete m_videoRenderer;
|
||||
delete m_imageCapture;
|
||||
#if defined(HAVE_WIDGETS)
|
||||
delete m_viewFinderWidget;
|
||||
#endif
|
||||
delete m_session;
|
||||
}
|
||||
|
||||
@@ -98,21 +78,8 @@ QMediaControl* DSCameraService::requestControl(const char *name)
|
||||
if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0)
|
||||
return m_imageCapture;
|
||||
|
||||
#if defined(HAVE_WIDGETS)
|
||||
if (qstrcmp(name, QVideoWidgetControl_iid) == 0) {
|
||||
if (!m_viewFinderWidget && !m_videoRenderer) {
|
||||
m_viewFinderWidget = new DSVideoWidgetControl(m_session);
|
||||
return m_viewFinderWidget;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (qstrcmp(name,QVideoRendererControl_iid) == 0) {
|
||||
#if defined(HAVE_WIDGETS)
|
||||
if (!m_videoRenderer && !m_viewFinderWidget) {
|
||||
#else
|
||||
if (!m_videoRenderer) {
|
||||
#endif
|
||||
m_videoRenderer = new DSVideoRendererControl(m_session, this);
|
||||
return m_videoRenderer;
|
||||
}
|
||||
@@ -131,14 +98,6 @@ void DSCameraService::releaseControl(QMediaControl *control)
|
||||
m_videoRenderer = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(HAVE_WIDGETS)
|
||||
if (control == m_viewFinderWidget) {
|
||||
delete m_viewFinderWidget;
|
||||
m_viewFinderWidget = 0;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -70,13 +70,9 @@ private:
|
||||
DSCameraControl *m_control;
|
||||
DSCameraSession *m_session;
|
||||
DSVideoOutputControl *m_videoOutput;
|
||||
#if defined(HAVE_WIDGETS)
|
||||
QMediaControl *m_viewFinderWidget;
|
||||
#endif
|
||||
DSVideoDeviceControl *m_videoDevice;
|
||||
QMediaControl *m_videoRenderer;
|
||||
DSImageCaptureControl *m_imageCapture;
|
||||
QByteArray m_device;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the Qt Toolkit.
|
||||
@@ -51,6 +51,7 @@
|
||||
#include <QtMultimedia/qvideoframe.h>
|
||||
#include <QtMultimedia/qabstractvideosurface.h>
|
||||
#include <QtMultimedia/qvideosurfaceformat.h>
|
||||
#include <private/qmediastoragelocation_p.h>
|
||||
|
||||
#include <tchar.h>
|
||||
#include <dshow.h>
|
||||
@@ -75,18 +76,8 @@ struct ISampleGrabber;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class DSVideoRenderer;
|
||||
class SampleGrabberCallbackPrivate;
|
||||
|
||||
|
||||
struct video_buffer {
|
||||
unsigned char* buffer;
|
||||
int length;
|
||||
qint64 time;
|
||||
};
|
||||
|
||||
typedef QMap<unsigned int, QList<QSize> > FormatResolutionMap;
|
||||
|
||||
class DSCameraSession : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -94,113 +85,82 @@ public:
|
||||
DSCameraSession(QObject *parent = 0);
|
||||
~DSCameraSession();
|
||||
|
||||
bool deviceReady();
|
||||
bool pictureInProgress();
|
||||
QCamera::Status status() const { return m_status; }
|
||||
|
||||
// camera controls
|
||||
|
||||
int framerate() const;
|
||||
void setFrameRate(int rate);
|
||||
int brightness() const;
|
||||
void setBrightness(int b);
|
||||
int contrast() const;
|
||||
void setContrast(int c);
|
||||
int saturation() const;
|
||||
void setSaturation(int s);
|
||||
int hue() const;
|
||||
void setHue(int h);
|
||||
int sharpness() const;
|
||||
void setSharpness(int s);
|
||||
int zoom() const;
|
||||
void setZoom(int z);
|
||||
bool backlightCompensation() const;
|
||||
void setBacklightCompensation(bool);
|
||||
int whitelevel() const;
|
||||
void setWhitelevel(int w);
|
||||
int rotation() const;
|
||||
void setRotation(int r);
|
||||
bool flash() const;
|
||||
void setFlash(bool f);
|
||||
bool autofocus() const;
|
||||
void setAutofocus(bool f);
|
||||
|
||||
QSize frameSize() const;
|
||||
void setFrameSize(const QSize& s);
|
||||
void setDevice(const QString &device);
|
||||
QList<QVideoFrame::PixelFormat> supportedPixelFormats();
|
||||
QVideoFrame::PixelFormat pixelFormat() const;
|
||||
void setPixelFormat(QVideoFrame::PixelFormat fmt);
|
||||
QList<QSize> supportedResolutions(QVideoFrame::PixelFormat format);
|
||||
|
||||
// media control
|
||||
bool load();
|
||||
bool unload();
|
||||
bool startPreview();
|
||||
bool stopPreview();
|
||||
|
||||
bool setOutputLocation(const QUrl &sink);
|
||||
QUrl outputLocation() const;
|
||||
qint64 position() const;
|
||||
int state() const;
|
||||
void record();
|
||||
void pause();
|
||||
void stop();
|
||||
bool isReadyForCapture();
|
||||
int captureImage(const QString &fileName);
|
||||
|
||||
void setSurface(QAbstractVideoSurface* surface);
|
||||
|
||||
int captureImage(const QString &fileName);
|
||||
|
||||
AM_MEDIA_TYPE StillMediaType;
|
||||
QList<video_buffer*> frames;
|
||||
SampleGrabberCallbackPrivate* StillCapCB;
|
||||
|
||||
QMutex mutex;
|
||||
|
||||
Q_SIGNALS:
|
||||
void stateChanged(QCamera::State);
|
||||
void statusChanged(QCamera::Status);
|
||||
void imageExposed(int id);
|
||||
void imageCaptured(int id, const QImage &preview);
|
||||
void imageSaved(int id, const QString &fileName);
|
||||
void readyForCaptureChanged(bool);
|
||||
void captureError(int id, int error, const QString &errorString);
|
||||
|
||||
private Q_SLOTS:
|
||||
void captureFrame();
|
||||
void presentFrame();
|
||||
void updateReadyForCapture();
|
||||
|
||||
private:
|
||||
QVideoSurfaceFormat actualFormat;
|
||||
QList<QVideoFrame::PixelFormat> types;
|
||||
void setStatus(QCamera::Status status);
|
||||
void populateCommonResolutions();
|
||||
|
||||
QTime timeStamp;
|
||||
bool graph;
|
||||
bool active;
|
||||
bool opened;
|
||||
bool available;
|
||||
QCamera::State m_state;
|
||||
QByteArray m_device;
|
||||
QUrl m_sink;
|
||||
DSVideoRenderer* m_output;
|
||||
QAbstractVideoSurface* m_surface;
|
||||
QVideoFrame::PixelFormat pixelF;
|
||||
QSize m_windowSize;
|
||||
FormatResolutionMap resolutions;
|
||||
void onFrameAvailable(const char *frameData, long len);
|
||||
void saveCapturedImage(int id, const QImage &image, const QString &path);
|
||||
|
||||
ICaptureGraphBuilder2* pBuild;
|
||||
IGraphBuilder* pGraph;
|
||||
IBaseFilter* pCap;
|
||||
IBaseFilter* pSG_Filter;
|
||||
ISampleGrabber *pSG;
|
||||
|
||||
|
||||
QString m_snapshot;
|
||||
int m_currentImageId;
|
||||
bool needsHorizontalMirroring;
|
||||
bool needsVerticalMirroring;
|
||||
protected:
|
||||
HRESULT getPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin);
|
||||
bool createFilterGraph();
|
||||
void updateProperties();
|
||||
bool setProperties();
|
||||
bool openStream();
|
||||
void closeStream();
|
||||
bool startStream();
|
||||
void stopStream();
|
||||
void suspendStream();
|
||||
void resumeStream();
|
||||
bool connectGraph();
|
||||
void disconnectGraph();
|
||||
void updateSourceCapabilities();
|
||||
bool configurePreviewFormat();
|
||||
|
||||
QMutex m_presentMutex;
|
||||
QMutex m_captureMutex;
|
||||
|
||||
// Capture Graph
|
||||
ICaptureGraphBuilder2* m_graphBuilder;
|
||||
IGraphBuilder* m_filterGraph;
|
||||
|
||||
// Source (camera)
|
||||
QString m_sourceDeviceName;
|
||||
IBaseFilter* m_sourceFilter;
|
||||
AM_MEDIA_TYPE m_sourcePreferredFormat;
|
||||
QSize m_sourcePreferredResolution;
|
||||
bool m_needsHorizontalMirroring;
|
||||
|
||||
// Preview
|
||||
IBaseFilter *m_previewFilter;
|
||||
ISampleGrabber *m_previewSampleGrabber;
|
||||
IBaseFilter *m_nullRendererFilter;
|
||||
QVideoFrame m_currentFrame;
|
||||
bool m_previewStarted;
|
||||
QAbstractVideoSurface* m_surface;
|
||||
QVideoSurfaceFormat m_previewSurfaceFormat;
|
||||
QVideoFrame::PixelFormat m_previewPixelFormat;
|
||||
QSize m_previewSize;
|
||||
|
||||
// Image capture
|
||||
QString m_imageCaptureFileName;
|
||||
QMediaStorageLocation m_fileNameGenerator;
|
||||
bool m_readyForCapture;
|
||||
int m_imageIdCounter;
|
||||
int m_currentImageId;
|
||||
QVideoFrame m_capturedFrame;
|
||||
|
||||
// Internal state
|
||||
QCamera::Status m_status;
|
||||
|
||||
friend class SampleGrabberCallbackPrivate;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -46,15 +46,19 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
DSImageCaptureControl::DSImageCaptureControl(DSCameraSession *session)
|
||||
:QCameraImageCaptureControl(session), m_session(session), m_ready(false)
|
||||
: QCameraImageCaptureControl(session)
|
||||
, m_session(session)
|
||||
{
|
||||
connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(updateState()));
|
||||
connect(m_session, SIGNAL(imageExposed(int)),
|
||||
this, SIGNAL(imageExposed(int)));
|
||||
connect(m_session, SIGNAL(imageCaptured(int,QImage)),
|
||||
this, SIGNAL(imageCaptured(int,QImage)));
|
||||
connect(m_session, SIGNAL(imageSaved(int,QString)),
|
||||
this, SIGNAL(imageSaved(int,QString)));
|
||||
connect(m_session, SIGNAL(readyForCaptureChanged(bool)),
|
||||
this, SIGNAL(readyForCaptureChanged(bool)));
|
||||
connect(m_session, SIGNAL(captureError(int,int,QString)),
|
||||
this, SIGNAL(error(int,int,QString)));
|
||||
}
|
||||
|
||||
DSImageCaptureControl::~DSImageCaptureControl()
|
||||
@@ -63,7 +67,7 @@ DSImageCaptureControl::~DSImageCaptureControl()
|
||||
|
||||
bool DSImageCaptureControl::isReadyForCapture() const
|
||||
{
|
||||
return m_ready;
|
||||
return m_session->isReadyForCapture();
|
||||
}
|
||||
|
||||
int DSImageCaptureControl::capture(const QString &fileName)
|
||||
@@ -71,12 +75,15 @@ int DSImageCaptureControl::capture(const QString &fileName)
|
||||
return m_session->captureImage(fileName);
|
||||
}
|
||||
|
||||
void DSImageCaptureControl::updateState()
|
||||
QCameraImageCapture::DriveMode DSImageCaptureControl::driveMode() const
|
||||
{
|
||||
bool ready = (m_session->state() == QCamera::ActiveState) &&
|
||||
!m_session->pictureInProgress();
|
||||
if(m_ready != ready)
|
||||
emit readyForCaptureChanged(m_ready = ready);
|
||||
return QCameraImageCapture::SingleImageCapture;
|
||||
}
|
||||
|
||||
void DSImageCaptureControl::setDriveMode(QCameraImageCapture::DriveMode mode)
|
||||
{
|
||||
if (mode != QCameraImageCapture::SingleImageCapture)
|
||||
qWarning("Drive mode not supported.");
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -52,23 +52,18 @@ class DSImageCaptureControl : public QCameraImageCaptureControl
|
||||
Q_OBJECT
|
||||
public:
|
||||
DSImageCaptureControl(DSCameraSession *session);
|
||||
virtual ~DSImageCaptureControl();
|
||||
~DSImageCaptureControl();
|
||||
|
||||
bool isReadyForCapture() const;
|
||||
int capture(const QString &fileName);
|
||||
|
||||
virtual QCameraImageCapture::DriveMode driveMode() const { return QCameraImageCapture::SingleImageCapture; }
|
||||
virtual void setDriveMode(QCameraImageCapture::DriveMode mode) { Q_UNUSED(mode) }
|
||||
|
||||
virtual void cancelCapture() {}
|
||||
|
||||
private slots:
|
||||
void updateState();
|
||||
QCameraImageCapture::DriveMode driveMode() const;
|
||||
void setDriveMode(QCameraImageCapture::DriveMode mode);
|
||||
|
||||
void cancelCapture() {}
|
||||
|
||||
private:
|
||||
DSCameraSession *m_session;
|
||||
bool m_ready;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -102,7 +102,6 @@ void DSVideoDeviceControl::enumerateDevices(QList<QByteArray> *devices, QStringL
|
||||
devices->clear();
|
||||
descriptions->clear();
|
||||
|
||||
CoInitialize(NULL);
|
||||
ICreateDevEnum* pDevEnum = NULL;
|
||||
IEnumMoniker* pEnum = NULL;
|
||||
// Create the System device enumerator
|
||||
@@ -148,7 +147,6 @@ void DSVideoDeviceControl::enumerateDevices(QList<QByteArray> *devices, QStringL
|
||||
}
|
||||
pDevEnum->Release();
|
||||
}
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
void DSVideoDeviceControl::setSelectedDevice(int index)
|
||||
|
||||
@@ -1,253 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** 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 Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtCore/qcoreevent.h>
|
||||
#include <QtCore/qtimer.h>
|
||||
|
||||
#include "dsvideowidgetcontrol.h"
|
||||
#include "dscamerasession.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
DSVideoWidgetSurface::DSVideoWidgetSurface(QLabel *pWidget, QObject *parent)
|
||||
: QAbstractVideoSurface(parent)
|
||||
{
|
||||
widget = pWidget;
|
||||
myPixmap = 0;
|
||||
}
|
||||
|
||||
QList<QVideoFrame::PixelFormat> DSVideoWidgetSurface::supportedPixelFormats(
|
||||
QAbstractVideoBuffer::HandleType handleType) const
|
||||
{
|
||||
if (handleType == QAbstractVideoBuffer::NoHandle) {
|
||||
return QList<QVideoFrame::PixelFormat>()
|
||||
<< QVideoFrame::Format_RGB32
|
||||
<< QVideoFrame::Format_RGB24;
|
||||
} else {
|
||||
return QList<QVideoFrame::PixelFormat>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DSVideoWidgetSurface::present(const QVideoFrame &frame)
|
||||
{
|
||||
QVideoFrame myFrame = frame;
|
||||
myFrame.map(QAbstractVideoBuffer::ReadOnly);
|
||||
QImage image(
|
||||
frame.bits(),
|
||||
frame.width(),
|
||||
frame.height(),
|
||||
frame.bytesPerLine(),
|
||||
imageFormat);
|
||||
if (image.isNull())
|
||||
{
|
||||
// Try to adapt
|
||||
QImage image2(
|
||||
frame.bits(),
|
||||
frame.width(),
|
||||
frame.height(),
|
||||
frame.bytesPerLine(),
|
||||
QImage::Format_RGB888);
|
||||
image = image2;
|
||||
}
|
||||
myFrame.unmap();
|
||||
delete myPixmap;
|
||||
myPixmap = new QPixmap(QPixmap::fromImage(image).scaled(widget->size()));
|
||||
widget->setPixmap(*myPixmap);
|
||||
widget->repaint();
|
||||
return true;
|
||||
}
|
||||
|
||||
void DSVideoWidgetSurface::setImageFormat(QImage::Format fmt)
|
||||
{
|
||||
imageFormat = fmt;
|
||||
}
|
||||
|
||||
void DSVideoWidgetSurface::updateVideoRect()
|
||||
{
|
||||
}
|
||||
|
||||
void DSVideoWidgetSurface::paint(QPainter *painter)
|
||||
{
|
||||
Q_UNUSED(painter)
|
||||
}
|
||||
|
||||
|
||||
DSVideoWidgetControl::DSVideoWidgetControl(DSCameraSession* session, QObject *parent) :
|
||||
QVideoWidgetControl(parent),
|
||||
m_session(session),
|
||||
m_widget(new QLabel()),
|
||||
m_fullScreen(false)
|
||||
{
|
||||
m_widget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
m_widget->setAlignment(Qt::AlignCenter);
|
||||
m_widget->setAttribute(Qt::WA_NoSystemBackground, true);
|
||||
|
||||
surface = new DSVideoWidgetSurface(m_widget);
|
||||
|
||||
QPalette palette;
|
||||
palette.setColor(QPalette::Background, Qt::black);
|
||||
m_widget->setPalette(palette);
|
||||
m_widget->setAutoFillBackground( true );
|
||||
|
||||
// Request QEvents
|
||||
m_widget->installEventFilter(this);
|
||||
m_windowId = m_widget->effectiveWinId();
|
||||
|
||||
surface->setImageFormat(QImage::Format_RGB888);
|
||||
session->setSurface(surface);
|
||||
}
|
||||
|
||||
DSVideoWidgetControl::~DSVideoWidgetControl()
|
||||
{
|
||||
delete m_widget;
|
||||
}
|
||||
|
||||
bool DSVideoWidgetControl::eventFilter(QObject *object, QEvent *e)
|
||||
{
|
||||
if (object == m_widget) {
|
||||
switch (e->type()) {
|
||||
case QEvent::ParentChange:
|
||||
case QEvent::WinIdChange:
|
||||
case QEvent::Show:
|
||||
m_windowId = m_widget->effectiveWinId();
|
||||
emit widgetUpdated();
|
||||
break;
|
||||
case QEvent::Resize:
|
||||
emit widgetResized(m_widget->size());
|
||||
break;
|
||||
case QEvent::PolishRequest:
|
||||
m_widget->ensurePolished();
|
||||
break;
|
||||
|
||||
default:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QWidget *DSVideoWidgetControl::videoWidget()
|
||||
{
|
||||
return m_widget;
|
||||
}
|
||||
|
||||
Qt::AspectRatioMode DSVideoWidgetControl::aspectRatioMode() const
|
||||
{
|
||||
return m_aspectRatioMode;
|
||||
}
|
||||
|
||||
void DSVideoWidgetControl::setAspectRatioMode(Qt::AspectRatioMode ratio)
|
||||
{
|
||||
if (m_aspectRatioMode==ratio) {
|
||||
return;
|
||||
}
|
||||
m_aspectRatioMode = ratio;
|
||||
|
||||
if (m_aspectRatioMode == Qt::KeepAspectRatio)
|
||||
m_widget->setScaledContents(false);
|
||||
else {
|
||||
m_widget->setScaledContents(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool DSVideoWidgetControl::isFullScreen() const
|
||||
{
|
||||
return m_fullScreen;
|
||||
}
|
||||
|
||||
void DSVideoWidgetControl::setFullScreen(bool fullScreen)
|
||||
{
|
||||
if (m_widget && !fullScreen && m_fullScreen) {
|
||||
m_widget->showNormal();
|
||||
m_fullScreen = false;
|
||||
} else if (m_widget && fullScreen) {
|
||||
m_widget->showFullScreen();
|
||||
m_fullScreen = true;
|
||||
}
|
||||
|
||||
emit fullScreenChanged(fullScreen);
|
||||
}
|
||||
|
||||
int DSVideoWidgetControl::brightness() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DSVideoWidgetControl::setBrightness(int brightness)
|
||||
{
|
||||
Q_UNUSED(brightness);
|
||||
}
|
||||
|
||||
int DSVideoWidgetControl::contrast() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DSVideoWidgetControl::setContrast(int contrast)
|
||||
{
|
||||
Q_UNUSED(contrast);
|
||||
}
|
||||
|
||||
int DSVideoWidgetControl::hue() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DSVideoWidgetControl::setHue(int hue)
|
||||
{
|
||||
Q_UNUSED(hue);
|
||||
}
|
||||
|
||||
int DSVideoWidgetControl::saturation() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DSVideoWidgetControl::setSaturation(int saturation)
|
||||
{
|
||||
Q_UNUSED(saturation);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
// End of file
|
||||
@@ -1,150 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** 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 Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef DSVIDEOWIDGETCONTROL_H
|
||||
#define DSVIDEOWIDGETCONTROL_H
|
||||
|
||||
#include <QtCore/qobject.h>
|
||||
#include <QtWidgets>
|
||||
#include <QtMultimedia/qvideoframe.h>
|
||||
#include <QtMultimedia/qabstractvideosurface.h>
|
||||
#include <QtMultimedia/qvideosurfaceformat.h>
|
||||
|
||||
#include <qvideowidgetcontrol.h>
|
||||
#include "dscameracontrol.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class DSVideoWidgetSurface : public QAbstractVideoSurface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DSVideoWidgetSurface(QLabel *pWidget, QObject *parent = 0);
|
||||
|
||||
QList<QVideoFrame::PixelFormat> supportedPixelFormats(
|
||||
QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const;
|
||||
|
||||
bool present(const QVideoFrame &frame);
|
||||
|
||||
QRect videoRect() const { return targetRect; }
|
||||
void updateVideoRect();
|
||||
|
||||
void paint(QPainter *painter);
|
||||
void setImageFormat(QImage::Format fmt);
|
||||
|
||||
private:
|
||||
QLabel *widget;
|
||||
QImage::Format imageFormat;
|
||||
QRect targetRect;
|
||||
QSize imageSize;
|
||||
QRect sourceRect;
|
||||
QPixmap* myPixmap;
|
||||
};
|
||||
|
||||
class DSVideoWidgetControl : public QVideoWidgetControl
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
DSVideoWidgetSurface* surface;
|
||||
public: // Constructor & Destructor
|
||||
|
||||
DSVideoWidgetControl(DSCameraSession* session, QObject *parent = 0);
|
||||
virtual ~DSVideoWidgetControl();
|
||||
|
||||
public: // QVideoWidgetControl
|
||||
|
||||
QWidget *videoWidget();
|
||||
|
||||
// Aspect Ratio
|
||||
Qt::AspectRatioMode aspectRatioMode() const;
|
||||
void setAspectRatioMode(Qt::AspectRatioMode ratio);
|
||||
|
||||
// Full Screen
|
||||
bool isFullScreen() const;
|
||||
void setFullScreen(bool fullScreen);
|
||||
|
||||
// Brightness
|
||||
int brightness() const;
|
||||
void setBrightness(int brightness);
|
||||
|
||||
// Contrast
|
||||
int contrast() const;
|
||||
void setContrast(int contrast);
|
||||
|
||||
// Hue
|
||||
int hue() const;
|
||||
void setHue(int hue);
|
||||
|
||||
// Saturation
|
||||
int saturation() const;
|
||||
void setSaturation(int saturation);
|
||||
|
||||
public: // Internal
|
||||
|
||||
bool eventFilter(QObject *object, QEvent *event);
|
||||
|
||||
/*
|
||||
Q_SIGNALS: // QVideoWidgetControl
|
||||
|
||||
void fullScreenChanged(bool fullScreen);
|
||||
void brightnessChanged(int brightness);
|
||||
void contrastChanged(int contrast);
|
||||
void hueChanged(int hue);
|
||||
void saturationChanged(int saturation);
|
||||
*/
|
||||
|
||||
Q_SIGNALS: // Internal Signals
|
||||
|
||||
void widgetResized(QSize size);
|
||||
void widgetUpdated();
|
||||
|
||||
private: // Data
|
||||
|
||||
DSCameraSession* m_session;
|
||||
QLabel *m_widget;
|
||||
WId m_windowId;
|
||||
Qt::AspectRatioMode m_aspectRatioMode;
|
||||
bool m_fullScreen;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // DSVideoWidgetControl_H
|
||||
@@ -4,7 +4,7 @@ PLUGIN_TYPE=mediaservice
|
||||
PLUGIN_CLASS_NAME = DSServicePlugin
|
||||
load(qt_plugin)
|
||||
|
||||
QT += multimedia
|
||||
QT += multimedia-private
|
||||
|
||||
HEADERS += dsserviceplugin.h
|
||||
SOURCES += dsserviceplugin.cpp
|
||||
|
||||
@@ -79,15 +79,32 @@ extern const CLSID CLSID_VideoInputDeviceCategory;
|
||||
|
||||
QT_USE_NAMESPACE
|
||||
|
||||
static int g_refCount = 0;
|
||||
void addRefCount()
|
||||
{
|
||||
if (++g_refCount == 1)
|
||||
CoInitialize(NULL);
|
||||
}
|
||||
|
||||
void releaseRefCount()
|
||||
{
|
||||
if (--g_refCount == 0)
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
QMediaService* DSServicePlugin::create(QString const& key)
|
||||
{
|
||||
#ifdef QMEDIA_DIRECTSHOW_CAMERA
|
||||
if (key == QLatin1String(Q_MEDIASERVICE_CAMERA))
|
||||
if (key == QLatin1String(Q_MEDIASERVICE_CAMERA)) {
|
||||
addRefCount();
|
||||
return new DSCameraService;
|
||||
}
|
||||
#endif
|
||||
#ifdef QMEDIA_DIRECTSHOW_PLAYER
|
||||
if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER))
|
||||
if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)) {
|
||||
addRefCount();
|
||||
return new DirectShowPlayerService;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
@@ -96,6 +113,7 @@ QMediaService* DSServicePlugin::create(QString const& key)
|
||||
void DSServicePlugin::release(QMediaService *service)
|
||||
{
|
||||
delete service;
|
||||
releaseRefCount();
|
||||
}
|
||||
|
||||
QMediaServiceProviderHint::Features DSServicePlugin::supportedFeatures(
|
||||
@@ -154,6 +172,8 @@ QString DSServicePlugin::deviceDescription(const QByteArray &service, const QByt
|
||||
|
||||
void DSServicePlugin::updateDevices() const
|
||||
{
|
||||
addRefCount();
|
||||
|
||||
m_defaultCameraDevice.clear();
|
||||
DSVideoDeviceControl::enumerateDevices(&m_cameraDevices, &m_cameraDescriptions);
|
||||
|
||||
@@ -162,6 +182,8 @@ void DSServicePlugin::updateDevices() const
|
||||
} else {
|
||||
m_defaultCameraDevice = m_cameraDevices.first();
|
||||
}
|
||||
|
||||
releaseRefCount();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -111,7 +111,6 @@ DirectShowPlayerService::DirectShowPlayerService(QObject *parent)
|
||||
, m_seekable(false)
|
||||
, m_atEnd(false)
|
||||
{
|
||||
CoInitialize(NULL);
|
||||
m_playerControl = new DirectShowPlayerControl(this);
|
||||
m_metaDataControl = new DirectShowMetaDataControl(this);
|
||||
m_audioEndpointControl = new DirectShowAudioEndpointControl(this);
|
||||
@@ -153,7 +152,6 @@ DirectShowPlayerService::~DirectShowPlayerService()
|
||||
#endif
|
||||
|
||||
::CloseHandle(m_taskHandle);
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
QMediaControl *DirectShowPlayerService::requestControl(const char *name)
|
||||
|
||||
Reference in New Issue
Block a user