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:
Yoann Lopes
2014-04-07 14:24:51 +02:00
parent f352e44df9
commit 389d66b3ed
15 changed files with 707 additions and 1509 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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)