summaryrefslogtreecommitdiffstats
path: root/src/plugins/directshow/camera
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/directshow/camera')
-rw-r--r--src/plugins/directshow/camera/camera.pri5
-rw-r--r--src/plugins/directshow/camera/dscameracontrol.cpp53
-rw-r--r--src/plugins/directshow/camera/dscameracontrol.h15
-rw-r--r--src/plugins/directshow/camera/dscameraservice.cpp41
-rw-r--r--src/plugins/directshow/camera/dscameraservice.h4
-rw-r--r--src/plugins/directshow/camera/dscamerasession.cpp1281
-rw-r--r--src/plugins/directshow/camera/dscamerasession.h162
-rw-r--r--src/plugins/directshow/camera/dsimagecapturecontrol.cpp23
-rw-r--r--src/plugins/directshow/camera/dsimagecapturecontrol.h13
-rw-r--r--src/plugins/directshow/camera/dsvideodevicecontrol.cpp2
-rw-r--r--src/plugins/directshow/camera/dsvideowidgetcontrol.cpp253
-rw-r--r--src/plugins/directshow/camera/dsvideowidgetcontrol.h150
12 files changed, 590 insertions, 1412 deletions
diff --git a/src/plugins/directshow/camera/camera.pri b/src/plugins/directshow/camera/camera.pri
index 2c0fe55b1..75fca4aad 100644
--- a/src/plugins/directshow/camera/camera.pri
+++ b/src/plugins/directshow/camera/camera.pri
@@ -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
diff --git a/src/plugins/directshow/camera/dscameracontrol.cpp b/src/plugins/directshow/camera/dscameracontrol.cpp
index 07035f5dd..15c669f41 100644
--- a/src/plugins/directshow/camera/dscameracontrol.cpp
+++ b/src/plugins/directshow/camera/dscameracontrol.cpp
@@ -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();
-}
-
-void DSCameraControl::stop()
-{
- m_session->stop();
+ if (m_captureMode != mode && isCaptureModeSupported(mode)) {
+ m_captureMode = mode;
+ emit captureModeChanged(mode);
+ }
}
-QCamera::State DSCameraControl::state() const
+QCamera::Status DSCameraControl::status() const
{
- return (QCamera::State)m_session->state();
+ return m_session->status();
}
QT_END_NAMESPACE
diff --git a/src/plugins/directshow/camera/dscameracontrol.h b/src/plugins/directshow/camera/dscameracontrol.h
index 5c7661643..36ab515bf 100644
--- a/src/plugins/directshow/camera/dscameracontrol.h
+++ b/src/plugins/directshow/camera/dscameracontrol.h
@@ -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;
};
diff --git a/src/plugins/directshow/camera/dscameraservice.cpp b/src/plugins/directshow/camera/dscameraservice.cpp
index 9d99c6dd6..b8a9b4aa7 100644
--- a/src/plugins/directshow/camera/dscameraservice.cpp
+++ b/src/plugins/directshow/camera/dscameraservice.cpp
@@ -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
diff --git a/src/plugins/directshow/camera/dscameraservice.h b/src/plugins/directshow/camera/dscameraservice.h
index fb8b7886a..ceb786414 100644
--- a/src/plugins/directshow/camera/dscameraservice.h
+++ b/src/plugins/directshow/camera/dscameraservice.h
@@ -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
diff --git a/src/plugins/directshow/camera/dscamerasession.cpp b/src/plugins/directshow/camera/dscamerasession.cpp
index 1ecc368e7..a8c85e5c6 100644
--- a/src/plugins/directshow/camera/dscamerasession.cpp
+++ b/src/plugins/directshow/camera/dscamerasession.cpp
@@ -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.
@@ -42,8 +42,11 @@
#include <QtCore/qdebug.h>
#include <QWidget>
#include <QFile>
+#include <QtConcurrent/QtConcurrentRun>
#include <QtMultimedia/qabstractvideobuffer.h>
#include <QtMultimedia/qvideosurfaceformat.h>
+#include <QtMultimedia/qcameraimagecapture.h>
+#include <private/qmemoryvideobuffer_p.h>
#include "dscamerasession.h"
#include "dsvideorenderer.h"
@@ -51,12 +54,23 @@
QT_BEGIN_NAMESPACE
-// If frames come in quicker than we display them, we allow the queue to build
-// up to this number before we start dropping them.
-const int LIMIT_FRAME = 5;
namespace {
// DirectShow helper implementation
+void _CopyMediaType(AM_MEDIA_TYPE *pmtTarget, const AM_MEDIA_TYPE *pmtSource)
+{
+ *pmtTarget = *pmtSource;
+ if (pmtTarget->cbFormat != 0) {
+ pmtTarget->pbFormat = reinterpret_cast<BYTE *>(CoTaskMemAlloc(pmtTarget->cbFormat));
+ if (pmtTarget->pbFormat)
+ memcpy(pmtTarget->pbFormat, pmtSource->pbFormat, pmtTarget->cbFormat);
+ }
+ if (pmtTarget->pUnk != NULL) {
+ // pUnk should not be used.
+ pmtTarget->pUnk->AddRef();
+ }
+}
+
void _FreeMediaType(AM_MEDIA_TYPE& mt)
{
if (mt.cbFormat != 0) {
@@ -70,14 +84,36 @@ void _FreeMediaType(AM_MEDIA_TYPE& mt)
mt.pUnk = NULL;
}
}
-
} // end namespace
+typedef QList<QSize> SizeList;
+Q_GLOBAL_STATIC(SizeList, commonPreviewResolutions)
+
+static HRESULT getPin(IBaseFilter *filter, PIN_DIRECTION pinDir, IPin **pin);
+
+
class SampleGrabberCallbackPrivate : public ISampleGrabberCB
{
public:
- STDMETHODIMP_(ULONG) AddRef() { return 1; }
- STDMETHODIMP_(ULONG) Release() { return 2; }
+ explicit SampleGrabberCallbackPrivate(DSCameraSession *session)
+ : m_ref(1)
+ , m_session(session)
+ { }
+
+ virtual ~SampleGrabberCallbackPrivate() { }
+
+ STDMETHODIMP_(ULONG) AddRef()
+ {
+ return InterlockedIncrement(&m_ref);
+ }
+
+ STDMETHODIMP_(ULONG) Release()
+ {
+ ULONG ref = InterlockedDecrement(&m_ref);
+ if (ref == 0)
+ delete this;
+ return ref;
+ }
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject)
{
@@ -101,143 +137,53 @@ public:
return E_NOTIMPL;
}
- STDMETHODIMP BufferCB(double Time, BYTE *pBuffer, long BufferLen)
+ STDMETHODIMP BufferCB(double time, BYTE *pBuffer, long bufferLen)
{
- if (!cs || active) {
- return S_OK;
- }
-
- if ((cs->StillMediaType.majortype != MEDIATYPE_Video) ||
- (cs->StillMediaType.formattype != FORMAT_VideoInfo) ||
- (cs->StillMediaType.cbFormat < sizeof(VIDEOINFOHEADER))) {
- return VFW_E_INVALIDMEDIATYPE;
- }
-
- active = true;
-
- if(toggle == true) {
- toggle = false;
- }
- else {
- toggle = true;
- }
-
- if(toggle) {
- active = false;
- return S_OK;
- }
-
- bool check = false;
- cs->mutex.lock();
+ // We display frames as they arrive, the presentation time is
+ // irrelevant
+ Q_UNUSED(time);
- if (cs->frames.size() > LIMIT_FRAME) {
- check = true;
+ if (m_session) {
+ m_session->onFrameAvailable(reinterpret_cast<const char *>(pBuffer),
+ bufferLen);
}
- if (check) {
- cs->mutex.unlock();
- // Frames building up. We're going to drop some here
- Sleep(100);
- active = false;
- return S_OK;
- }
- cs->mutex.unlock();
-
- unsigned char* vidData = new unsigned char[BufferLen];
- memcpy(vidData, pBuffer, BufferLen);
-
- cs->mutex.lock();
-
- video_buffer* buf = new video_buffer;
- buf->buffer = vidData;
- buf->length = BufferLen;
- buf->time = (qint64)Time;
-
- cs->frames.append(buf);
-
- cs->mutex.unlock();
-
- QMetaObject::invokeMethod(cs, "captureFrame", Qt::QueuedConnection);
-
- active = false;
-
return S_OK;
}
- DSCameraSession* cs;
- bool active;
- bool toggle;
+private:
+ ULONG m_ref;
+ DSCameraSession *m_session;
};
DSCameraSession::DSCameraSession(QObject *parent)
: QObject(parent)
- ,m_currentImageId(0)
- , needsHorizontalMirroring(false)
- , needsVerticalMirroring(true)
-{
- pBuild = NULL;
- pGraph = NULL;
- pCap = NULL;
- pSG_Filter = NULL;
- pSG = NULL;
-
- opened = false;
- available = false;
- resolutions.clear();
- m_state = QCamera::UnloadedState;
- m_device = "default";
-
- StillCapCB = new SampleGrabberCallbackPrivate;
- StillCapCB->cs = this;
- StillCapCB->active = false;
- StillCapCB->toggle = false;
-
- m_output = 0;
- m_surface = 0;
- pixelF = QVideoFrame::Format_Invalid;
-
- graph = false;
- active = false;
-
- ::CoInitialize(NULL);
+ , m_graphBuilder(Q_NULLPTR)
+ , m_filterGraph(Q_NULLPTR)
+ , m_sourceDeviceName(QLatin1String("default"))
+ , m_sourceFilter(Q_NULLPTR)
+ , m_needsHorizontalMirroring(false)
+ , m_previewFilter(Q_NULLPTR)
+ , m_previewSampleGrabber(Q_NULLPTR)
+ , m_nullRendererFilter(Q_NULLPTR)
+ , m_previewStarted(false)
+ , m_surface(Q_NULLPTR)
+ , m_previewPixelFormat(QVideoFrame::Format_Invalid)
+ , m_readyForCapture(false)
+ , m_imageIdCounter(0)
+ , m_currentImageId(-1)
+ , m_status(QCamera::UnloadedStatus)
+{
+ ZeroMemory(&m_sourcePreferredFormat, sizeof(m_sourcePreferredFormat));
+
+ connect(this, SIGNAL(statusChanged(QCamera::Status)),
+ this, SLOT(updateReadyForCapture()));
}
DSCameraSession::~DSCameraSession()
{
- if (opened) {
- closeStream();
- }
-
- CoUninitialize();
-
- SAFE_RELEASE(pCap);
- SAFE_RELEASE(pSG_Filter);
- SAFE_RELEASE(pGraph);
- SAFE_RELEASE(pBuild);
-
- if (StillCapCB) {
- delete StillCapCB;
- }
-}
-
-int DSCameraSession::captureImage(const QString &fileName)
-{
- emit readyForCaptureChanged(false);
-
- // We're going to do this in one big synchronous call
- m_currentImageId++;
- if (fileName.isEmpty()) {
- m_snapshot = "img.jpg";
- } else {
- m_snapshot = fileName;
- }
-
- if (!active) {
- startStream();
- }
-
- return m_currentImageId;
+ unload();
}
void DSCameraSession::setSurface(QAbstractVideoSurface* surface)
@@ -245,415 +191,260 @@ void DSCameraSession::setSurface(QAbstractVideoSurface* surface)
m_surface = surface;
}
-bool DSCameraSession::deviceReady()
-{
- return available;
-}
-
-bool DSCameraSession::pictureInProgress()
+void DSCameraSession::setDevice(const QString &device)
{
- return m_snapshot.isEmpty();
+ m_sourceDeviceName = device;
}
-int DSCameraSession::framerate() const
+bool DSCameraSession::load()
{
- return -1;
-}
+ unload();
-void DSCameraSession::setFrameRate(int rate)
-{
- Q_UNUSED(rate)
-}
+ setStatus(QCamera::LoadingStatus);
-int DSCameraSession::brightness() const
-{
- return -1;
-}
+ bool succeeded = createFilterGraph();
+ if (succeeded)
+ setStatus(QCamera::LoadedStatus);
+ else
+ setStatus(QCamera::UnavailableStatus);
-void DSCameraSession::setBrightness(int b)
-{
- Q_UNUSED(b)
+ return succeeded;
}
-int DSCameraSession::contrast() const
+bool DSCameraSession::unload()
{
- return -1;
-}
-
-void DSCameraSession::setContrast(int c)
-{
- Q_UNUSED(c)
-}
+ if (!m_graphBuilder)
+ return false;
-int DSCameraSession::saturation() const
-{
- return -1;
-}
+ if (!stopPreview())
+ return false;
-void DSCameraSession::setSaturation(int s)
-{
- Q_UNUSED(s)
-}
+ setStatus(QCamera::UnloadingStatus);
-int DSCameraSession::hue() const
-{
- return -1;
-}
+ m_needsHorizontalMirroring = false;
+ m_sourcePreferredResolution = QSize();
+ _FreeMediaType(m_sourcePreferredFormat);
+ ZeroMemory(&m_sourcePreferredFormat, sizeof(m_sourcePreferredFormat));
+ SAFE_RELEASE(m_sourceFilter);
+ SAFE_RELEASE(m_previewSampleGrabber);
+ SAFE_RELEASE(m_previewFilter);
+ SAFE_RELEASE(m_nullRendererFilter);
+ SAFE_RELEASE(m_filterGraph);
+ SAFE_RELEASE(m_graphBuilder);
-void DSCameraSession::setHue(int h)
-{
- Q_UNUSED(h)
-}
+ setStatus(QCamera::UnloadedStatus);
-int DSCameraSession::sharpness() const
-{
- return -1;
-}
-
-void DSCameraSession::setSharpness(int s)
-{
- Q_UNUSED(s)
+ return true;
}
-int DSCameraSession::zoom() const
+bool DSCameraSession::startPreview()
{
- return -1;
-}
+ if (m_previewStarted)
+ return true;
-void DSCameraSession::setZoom(int z)
-{
- Q_UNUSED(z)
-}
+ if (!m_graphBuilder)
+ return false;
-bool DSCameraSession::backlightCompensation() const
-{
- return false;
-}
+ setStatus(QCamera::StartingStatus);
-void DSCameraSession::setBacklightCompensation(bool b)
-{
- Q_UNUSED(b)
-}
+ HRESULT hr = S_OK;
+ IMediaControl* pControl = 0;
-int DSCameraSession::whitelevel() const
-{
- return -1;
-}
+ if (!configurePreviewFormat()) {
+ qWarning() << "Failed to configure preview format";
+ goto failed;
+ }
-void DSCameraSession::setWhitelevel(int w)
-{
- Q_UNUSED(w)
-}
+ if (!connectGraph())
+ goto failed;
-int DSCameraSession::rotation() const
-{
- return 0;
-}
+ if (m_surface)
+ m_surface->start(m_previewSurfaceFormat);
-void DSCameraSession::setRotation(int r)
-{
- Q_UNUSED(r)
-}
+ hr = m_filterGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);
+ if (FAILED(hr)) {
+ qWarning() << "failed to get stream control";
+ goto failed;
+ }
+ hr = pControl->Run();
+ pControl->Release();
-bool DSCameraSession::flash() const
-{
- return false;
-}
+ if (FAILED(hr)) {
+ qWarning() << "failed to start";
+ goto failed;
+ }
-void DSCameraSession::setFlash(bool f)
-{
- Q_UNUSED(f)
-}
+ setStatus(QCamera::ActiveStatus);
+ m_previewStarted = true;
+ return true;
-bool DSCameraSession::autofocus() const
-{
+failed:
+ // go back to a clean state
+ if (m_surface && m_surface->isActive())
+ m_surface->stop();
+ disconnectGraph();
+ setStatus(QCamera::LoadedStatus);
return false;
}
-void DSCameraSession::setAutofocus(bool f)
+bool DSCameraSession::stopPreview()
{
- Q_UNUSED(f)
-}
-
-QSize DSCameraSession::frameSize() const
-{
- return m_windowSize;
-}
-
-void DSCameraSession::setFrameSize(const QSize& s)
-{
- if (supportedResolutions(pixelF).contains(s))
- m_windowSize = s;
- else
- qWarning() << "frame size if not supported for current pixel format, no change";
-}
-
-void DSCameraSession::setDevice(const QString &device)
-{
- if(opened)
- stopStream();
-
- if(graph) {
- SAFE_RELEASE(pCap);
- SAFE_RELEASE(pSG_Filter);
- SAFE_RELEASE(pGraph);
- SAFE_RELEASE(pBuild);
- }
-
- available = false;
- m_state = QCamera::LoadedState;
-
- CoInitialize(NULL);
-
- ICreateDevEnum* pDevEnum = NULL;
- IEnumMoniker* pEnum = NULL;
+ if (!m_previewStarted)
+ return true;
- // Create the System device enumerator
- HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
- CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
- reinterpret_cast<void**>(&pDevEnum));
- if(SUCCEEDED(hr)) {
- // Create the enumerator for the video capture category
- hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
- if (S_OK == hr) {
- pEnum->Reset();
- // go through and find all video capture devices
- IMoniker* pMoniker = NULL;
- IMalloc *mallocInterface = 0;
- CoGetMalloc(1, (LPMALLOC*)&mallocInterface);
- while(pEnum->Next(1, &pMoniker, NULL) == S_OK) {
+ setStatus(QCamera::StoppingStatus);
- BSTR strName = 0;
- hr = pMoniker->GetDisplayName(NULL, NULL, &strName);
- if (SUCCEEDED(hr)) {
- QString temp(QString::fromWCharArray(strName));
- mallocInterface->Free(strName);
- if(temp.contains(device)) {
- available = true;
- }
- }
-
- pMoniker->Release();
- }
- mallocInterface->Release();
- pEnum->Release();
- }
- pDevEnum->Release();
+ IMediaControl* pControl = 0;
+ HRESULT hr = m_filterGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);
+ if (FAILED(hr)) {
+ qWarning() << "failed to get stream control";
+ goto failed;
}
- CoUninitialize();
- if(available) {
- m_device = QByteArray(device.toUtf8().constData());
- graph = createFilterGraph();
- if(!graph)
- available = false;
+ hr = pControl->Stop();
+ pControl->Release();
+ if (FAILED(hr)) {
+ qWarning() << "failed to stop";
+ goto failed;
}
-}
-QList<QVideoFrame::PixelFormat> DSCameraSession::supportedPixelFormats()
-{
- return types;
-}
-
-QVideoFrame::PixelFormat DSCameraSession::pixelFormat() const
-{
- return pixelF;
-}
+ disconnectGraph();
-void DSCameraSession::setPixelFormat(QVideoFrame::PixelFormat fmt)
-{
- pixelF = fmt;
-}
+ m_previewStarted = false;
+ setStatus(QCamera::LoadedStatus);
+ return true;
-QList<QSize> DSCameraSession::supportedResolutions(QVideoFrame::PixelFormat format)
-{
- if (!resolutions.contains(format))
- return QList<QSize>();
- return resolutions.value(format);
+failed:
+ setStatus(QCamera::ActiveStatus);
+ return false;
}
-bool DSCameraSession::setOutputLocation(const QUrl &sink)
+void DSCameraSession::setStatus(QCamera::Status status)
{
- m_sink = sink;
+ if (m_status == status)
+ return;
- return true;
+ m_status = status;
+ emit statusChanged(m_status);
}
-QUrl DSCameraSession::outputLocation() const
+bool DSCameraSession::isReadyForCapture()
{
- return m_sink;
+ return m_readyForCapture;
}
-qint64 DSCameraSession::position() const
+void DSCameraSession::updateReadyForCapture()
{
- return timeStamp.elapsed();
+ bool isReady = (m_status == QCamera::ActiveStatus && m_imageCaptureFileName.isEmpty());
+ if (isReady != m_readyForCapture) {
+ m_readyForCapture = isReady;
+ emit readyForCaptureChanged(isReady);
+ }
}
-int DSCameraSession::state() const
+int DSCameraSession::captureImage(const QString &fileName)
{
- return int(m_state);
-}
+ ++m_imageIdCounter;
-void DSCameraSession::record()
-{
- if(opened) {
- return;
+ if (!m_readyForCapture) {
+ emit captureError(m_imageIdCounter, QCameraImageCapture::NotReadyError,
+ tr("Camera not ready for capture"));
+ return m_imageIdCounter;
}
- if(m_surface) {
+ m_imageCaptureFileName = m_fileNameGenerator.generateFileName(fileName,
+ QMediaStorageLocation::Pictures,
+ QLatin1String("IMG_"),
+ QLatin1String("jpg"));
- if (!graph)
- graph = createFilterGraph();
+ updateReadyForCapture();
- if (types.isEmpty()) {
- if (pixelF == QVideoFrame::Format_Invalid)
- pixelF = QVideoFrame::Format_RGB32;
- if (!m_windowSize.isValid())
- m_windowSize = QSize(320, 240);
- }
- actualFormat = QVideoSurfaceFormat(m_windowSize, pixelF);
-
- if (!m_surface->isFormatSupported(actualFormat) && !types.isEmpty()) {
- // enumerate through camera formats
- QList<QVideoFrame::PixelFormat> fmts = m_surface->supportedPixelFormats();
- foreach(QVideoFrame::PixelFormat f, types) {
- if (fmts.contains(f)) {
- pixelF = f;
- if (!resolutions[pixelF].contains(m_windowSize)) {
- Q_ASSERT(!resolutions[pixelF].isEmpty());
- m_windowSize = resolutions[pixelF].first();
- }
- actualFormat = QVideoSurfaceFormat(m_windowSize, pixelF);
- break;
- }
- }
- }
+ m_captureMutex.lock();
+ m_currentImageId = m_imageIdCounter;
+ m_captureMutex.unlock();
- if (m_surface->isFormatSupported(actualFormat)) {
- m_surface->start(actualFormat);
- m_state = QCamera::ActiveState;
- emit stateChanged(QCamera::ActiveState);
- } else {
- qWarning() << "surface doesn't support camera format, cant start";
- m_state = QCamera::LoadedState;
- emit stateChanged(QCamera::LoadedState);
- return;
- }
- } else {
- qWarning() << "no video surface, cant start";
- m_state = QCamera::LoadedState;
- emit stateChanged(QCamera::LoadedState);
- return;
- }
-
- opened = startStream();
-
- if (!opened) {
- qWarning() << "Stream did not open";
- m_state = QCamera::LoadedState;
- emit stateChanged(QCamera::LoadedState);
- }
+ return m_imageIdCounter;
}
-void DSCameraSession::pause()
+void DSCameraSession::onFrameAvailable(const char *frameData, long len)
{
- suspendStream();
-}
+ // !!! Not called on the main thread
-void DSCameraSession::stop()
-{
- if(!opened) {
- return;
- }
+ // Deep copy, the data might be modified or freed after the callback returns
+ QByteArray data(frameData, len);
- stopStream();
- opened = false;
- m_state = QCamera::LoadedState;
- emit stateChanged(QCamera::LoadedState);
-}
+ m_presentMutex.lock();
-void DSCameraSession::captureFrame()
-{
- if(m_surface && frames.count() > 0) {
+ // (We should be getting only RGB32 data)
+ int stride = m_previewSize.width() * 4;
- QImage image;
+ // In case the source produces frames faster than we can display them,
+ // only keep the most recent one
+ m_currentFrame = QVideoFrame(new QMemoryVideoBuffer(data, stride),
+ m_previewSize,
+ m_previewPixelFormat);
- if(pixelF == QVideoFrame::Format_RGB24) {
+ m_presentMutex.unlock();
- mutex.lock();
+ // Image capture
+ QMutexLocker locker(&m_captureMutex);
+ if (m_currentImageId != -1 && !m_capturedFrame.isValid()) {
+ m_capturedFrame = m_currentFrame;
+ emit imageExposed(m_currentImageId);
+ }
- image = QImage(frames.at(0)->buffer,m_windowSize.width(),m_windowSize.height(),
- QImage::Format_RGB888).rgbSwapped().mirrored(needsHorizontalMirroring, needsVerticalMirroring);
+ QMetaObject::invokeMethod(this, "presentFrame", Qt::QueuedConnection);
+}
- QVideoFrame frame(image);
- frame.setStartTime(frames.at(0)->time);
+void DSCameraSession::presentFrame()
+{
+ m_presentMutex.lock();
- mutex.unlock();
+ if (m_currentFrame.isValid() && m_surface) {
+ m_surface->present(m_currentFrame);
+ m_currentFrame = QVideoFrame();
+ }
- m_surface->present(frame);
+ m_presentMutex.unlock();
- } else if (pixelF == QVideoFrame::Format_RGB32) {
+ m_captureMutex.lock();
- mutex.lock();
+ if (m_capturedFrame.isValid()) {
+ Q_ASSERT(m_previewPixelFormat == QVideoFrame::Format_RGB32);
- image = QImage(frames.at(0)->buffer,m_windowSize.width(),m_windowSize.height(),
- QImage::Format_RGB32).mirrored(needsHorizontalMirroring, needsVerticalMirroring);
+ m_capturedFrame.map(QAbstractVideoBuffer::ReadOnly);
- QVideoFrame frame(image);
- frame.setStartTime(frames.at(0)->time);
+ QImage image = QImage(m_capturedFrame.bits(),
+ m_previewSize.width(), m_previewSize.height(),
+ QImage::Format_RGB32);
- mutex.unlock();
+ image = image.mirrored(m_needsHorizontalMirroring); // also causes a deep copy of the data
- m_surface->present(frame);
+ m_capturedFrame.unmap();
- } else {
- qWarning() << "TODO:captureFrame() format =" << pixelF;
- }
+ emit imageCaptured(m_currentImageId, image);
- if (m_snapshot.length() > 0) {
- emit imageCaptured(m_currentImageId, image);
- image.save(m_snapshot,"JPG");
- emit imageSaved(m_currentImageId, m_snapshot);
- m_snapshot.clear();
- emit readyForCaptureChanged(true);
- }
+ QtConcurrent::run(this, &DSCameraSession::saveCapturedImage,
+ m_currentImageId, image, m_imageCaptureFileName);
- mutex.lock();
- if (frames.isEmpty()) {
- qWarning() << "Frames over-run";
- }
+ m_imageCaptureFileName.clear();
+ m_currentImageId = -1;
+ updateReadyForCapture();
- video_buffer* buf = frames.takeFirst();
- delete buf->buffer;
- delete buf;
- mutex.unlock();
+ m_capturedFrame = QVideoFrame();
}
+
+ m_captureMutex.unlock();
}
-HRESULT DSCameraSession::getPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin)
+void DSCameraSession::saveCapturedImage(int id, const QImage &image, const QString &path)
{
- *ppPin = 0;
- IEnumPins *pEnum = 0;
- IPin *pPin = 0;
-
- HRESULT hr = pFilter->EnumPins(&pEnum);
- if(FAILED(hr)) {
- return hr;
- }
-
- pEnum->Reset();
- while(pEnum->Next(1, &pPin, NULL) == S_OK) {
- PIN_DIRECTION ThisPinDir;
- pPin->QueryDirection(&ThisPinDir);
- if(ThisPinDir == PinDir) {
- pEnum->Release();
- *ppPin = pPin;
- return S_OK;
- }
- pEnum->Release();
+ if (image.save(path, "JPG")) {
+ emit imageSaved(id, path);
+ } else {
+ emit captureError(id, QCameraImageCapture::ResourceError,
+ tr("Could not save image to file."));
}
- pEnum->Release();
- return E_FAIL;
}
bool DSCameraSession::createFilterGraph()
@@ -661,35 +452,34 @@ bool DSCameraSession::createFilterGraph()
// Previously containered in <qedit.h>.
static const IID iID_ISampleGrabber = { 0x6B652FFF, 0x11FE, 0x4fce, { 0x92, 0xAD, 0x02, 0x66, 0xB5, 0xD7, 0xC7, 0x8F } };
static const CLSID cLSID_SampleGrabber = { 0xC1F400A0, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } };
+ static const CLSID cLSID_NullRenderer = { 0xC1F400A4, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } };
HRESULT hr;
IMoniker* pMoniker = NULL;
ICreateDevEnum* pDevEnum = NULL;
IEnumMoniker* pEnum = NULL;
- CoInitialize(NULL);
-
// Create the filter graph
hr = CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC,
- IID_IGraphBuilder, (void**)&pGraph);
+ IID_IGraphBuilder, (void**)&m_filterGraph);
if (FAILED(hr)) {
- qWarning()<<"failed to create filter graph";
- return false;
+ qWarning() << "failed to create filter graph";
+ goto failed;
}
// Create the capture graph builder
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC,
- IID_ICaptureGraphBuilder2, (void**)&pBuild);
+ IID_ICaptureGraphBuilder2, (void**)&m_graphBuilder);
if (FAILED(hr)) {
- qWarning()<<"failed to create graph builder";
- return false;
+ qWarning() << "failed to create graph builder";
+ goto failed;
}
// Attach the filter graph to the capture graph
- hr = pBuild->SetFiltergraph(pGraph);
+ hr = m_graphBuilder->SetFiltergraph(m_filterGraph);
if (FAILED(hr)) {
- qWarning()<<"failed to connect capture graph and filter graph";
- return false;
+ qWarning() << "failed to connect capture graph and filter graph";
+ goto failed;
}
// Find the Capture device
@@ -712,8 +502,8 @@ bool DSCameraSession::createFilterGraph()
if (SUCCEEDED(hr)) {
QString output = QString::fromWCharArray(strName);
mallocInterface->Free(strName);
- if (m_device.contains(output.toUtf8().constData())) {
- hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
+ if (m_sourceDeviceName.contains(output)) {
+ hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&m_sourceFilter);
if (SUCCEEDED(hr)) {
pMoniker->Release();
break;
@@ -723,9 +513,9 @@ bool DSCameraSession::createFilterGraph()
pMoniker->Release();
}
mallocInterface->Release();
- if (NULL == pCap)
+ if (NULL == m_sourceFilter)
{
- if (m_device.contains("default"))
+ if (m_sourceDeviceName.contains(QLatin1String("default")))
{
pEnum->Reset();
// still have to loop to discard bind to storage failure case
@@ -740,7 +530,7 @@ bool DSCameraSession::createFilterGraph()
// No need to get the description, just grab it
- hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
+ hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&m_sourceFilter);
pPropBag->Release();
pMoniker->Release();
if (SUCCEEDED(hr)) {
@@ -757,443 +547,314 @@ bool DSCameraSession::createFilterGraph()
}
}
+ if (!m_sourceFilter) {
+ qWarning() << "No capture device found";
+ goto failed;
+ }
+
// Sample grabber filter
hr = CoCreateInstance(cLSID_SampleGrabber, NULL,CLSCTX_INPROC,
- IID_IBaseFilter, (void**)&pSG_Filter);
+ IID_IBaseFilter, (void**)&m_previewFilter);
if (FAILED(hr)) {
qWarning() << "failed to create sample grabber";
- return false;
+ goto failed;
}
- hr = pSG_Filter->QueryInterface(iID_ISampleGrabber, (void**)&pSG);
+ hr = m_previewFilter->QueryInterface(iID_ISampleGrabber, (void**)&m_previewSampleGrabber);
if (FAILED(hr)) {
qWarning() << "failed to get sample grabber";
- return false;
+ goto failed;
}
- pSG->SetOneShot(FALSE);
- pSG->SetBufferSamples(TRUE);
- pSG->SetCallback(StillCapCB, 1);
-
- updateProperties();
- CoUninitialize();
- return true;
-}
-
-void DSCameraSession::updateProperties()
-{
- HRESULT hr;
- AM_MEDIA_TYPE *pmt = NULL;
- VIDEOINFOHEADER *pvi = NULL;
- VIDEO_STREAM_CONFIG_CAPS scc;
- IAMStreamConfig* pConfig = 0;
- hr = pBuild->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,pCap,
- IID_IAMStreamConfig, (void**)&pConfig);
- if (FAILED(hr)) {
- qWarning()<<"failed to get config on capture device";
- return;
+ {
+ SampleGrabberCallbackPrivate *callback = new SampleGrabberCallbackPrivate(this);
+ m_previewSampleGrabber->SetCallback(callback, 1);
+ m_previewSampleGrabber->SetOneShot(FALSE);
+ m_previewSampleGrabber->SetBufferSamples(FALSE);
+ callback->Release();
}
- int iCount;
- int iSize;
- hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize);
+ // Null renderer. Input connected to the sample grabber's output. Simply
+ // discard the samples it receives.
+ hr = CoCreateInstance(cLSID_NullRenderer, NULL, CLSCTX_INPROC,
+ IID_IBaseFilter, (void**)&m_nullRendererFilter);
if (FAILED(hr)) {
- qWarning()<<"failed to get capabilities";
- return;
+ qWarning() << "failed to create null renderer";
+ goto failed;
}
- QList<QSize> sizes;
- QVideoFrame::PixelFormat f = QVideoFrame::Format_Invalid;
+ updateSourceCapabilities();
- types.clear();
- resolutions.clear();
- IAMVideoControl *pVideoControl = 0;
- hr = pBuild->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,pCap,
- IID_IAMVideoControl, (void**)&pVideoControl);
- if (FAILED(hr)) {
- qWarning() << "Failed to get the video control";
- } else {
- IPin *pPin = 0;
- if (pCap) {
- hr = getPin(pCap, PINDIR_OUTPUT, &pPin);
- if (FAILED(hr)) {
- qWarning() << "Failed to get the pin for the video control";
- } else {
- long supportedModes;
- hr = pVideoControl->GetCaps(pPin, &supportedModes);
- if (FAILED(hr)) {
- qWarning() << "Failed to get the supported modes of the video control";
- } else if (supportedModes & VideoControlFlag_FlipHorizontal || supportedModes & VideoControlFlag_FlipVertical) {
- long mode;
- hr = pVideoControl->GetMode(pPin, &mode);
- if (FAILED(hr)) {
- qWarning() << "Failed to get the mode of the video control";
- } else {
- if (supportedModes & VideoControlFlag_FlipHorizontal)
- needsHorizontalMirroring = (mode & VideoControlFlag_FlipHorizontal);
- if (supportedModes & VideoControlFlag_FlipVertical)
- needsVerticalMirroring = (mode & VideoControlFlag_FlipVertical);
- }
- }
- pPin->Release();
- }
- }
- pVideoControl->Release();
- }
- for (int iIndex = 0; iIndex < iCount; iIndex++) {
- hr = pConfig->GetStreamCaps(iIndex, &pmt, reinterpret_cast<BYTE*>(&scc));
- if (hr == S_OK) {
- pvi = (VIDEOINFOHEADER*)pmt->pbFormat;
- if ((pmt->majortype == MEDIATYPE_Video) &&
- (pmt->formattype == FORMAT_VideoInfo)) {
- // Add types
- if (pmt->subtype == MEDIASUBTYPE_RGB24) {
- if (!types.contains(QVideoFrame::Format_RGB24)) {
- types.append(QVideoFrame::Format_RGB24);
- f = QVideoFrame::Format_RGB24;
- }
- } else if (pmt->subtype == MEDIASUBTYPE_RGB32) {
- if (!types.contains(QVideoFrame::Format_RGB32)) {
- types.append(QVideoFrame::Format_RGB32);
- f = QVideoFrame::Format_RGB32;
- }
- } else if (pmt->subtype == MEDIASUBTYPE_YUY2) {
- if (!types.contains(QVideoFrame::Format_YUYV)) {
- types.append(QVideoFrame::Format_YUYV);
- f = QVideoFrame::Format_YUYV;
- }
- } else if (pmt->subtype == MEDIASUBTYPE_MJPG) {
- } else if (pmt->subtype == MEDIASUBTYPE_I420) {
- if (!types.contains(QVideoFrame::Format_YUV420P)) {
- types.append(QVideoFrame::Format_YUV420P);
- f = QVideoFrame::Format_YUV420P;
- }
- } else if (pmt->subtype == MEDIASUBTYPE_RGB555) {
- if (!types.contains(QVideoFrame::Format_RGB555)) {
- types.append(QVideoFrame::Format_RGB555);
- f = QVideoFrame::Format_RGB555;
- }
- } else if (pmt->subtype == MEDIASUBTYPE_YVU9) {
- } else if (pmt->subtype == MEDIASUBTYPE_UYVY) {
- if (!types.contains(QVideoFrame::Format_UYVY)) {
- types.append(QVideoFrame::Format_UYVY);
- f = QVideoFrame::Format_UYVY;
- }
- } else {
- qWarning() << "UNKNOWN FORMAT: " << pmt->subtype.Data1;
- }
- // Add resolutions
- QSize res(pvi->bmiHeader.biWidth, pvi->bmiHeader.biHeight);
- if (!resolutions.contains(f)) {
- sizes.clear();
- resolutions.insert(f,sizes);
- }
- resolutions[f].append(res);
- }
- }
- }
- pConfig->Release();
+ return true;
- if (!types.isEmpty()) {
- // Add RGB formats and let directshow do color space conversion if required.
- if (!types.contains(QVideoFrame::Format_RGB24)) {
- types.append(QVideoFrame::Format_RGB24);
- resolutions.insert(QVideoFrame::Format_RGB24, resolutions[types.first()]);
- }
- if (!types.contains(QVideoFrame::Format_RGB32)) {
- types.append(QVideoFrame::Format_RGB32);
- resolutions.insert(QVideoFrame::Format_RGB32, resolutions[types.first()]);
- }
- }
+failed:
+ m_needsHorizontalMirroring = false;
+ m_sourcePreferredResolution = QSize();
+ _FreeMediaType(m_sourcePreferredFormat);
+ ZeroMemory(&m_sourcePreferredFormat, sizeof(m_sourcePreferredFormat));
+ SAFE_RELEASE(m_sourceFilter);
+ SAFE_RELEASE(m_previewSampleGrabber);
+ SAFE_RELEASE(m_previewFilter);
+ SAFE_RELEASE(m_nullRendererFilter);
+ SAFE_RELEASE(m_filterGraph);
+ SAFE_RELEASE(m_graphBuilder);
+
+ return false;
}
-bool DSCameraSession::setProperties()
+bool DSCameraSession::configurePreviewFormat()
{
- CoInitialize(NULL);
+ // We only support RGB32, if the capture source doesn't support
+ // that format, the graph builder will automatically insert a
+ // converter.
- HRESULT hr;
- AM_MEDIA_TYPE am_media_type;
- AM_MEDIA_TYPE *pmt = NULL;
- VIDEOINFOHEADER *pvi = NULL;
- VIDEO_STREAM_CONFIG_CAPS scc;
-
- IAMStreamConfig* pConfig = 0;
- hr = pBuild->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pCap,
- IID_IAMStreamConfig, (void**)&pConfig);
- if(FAILED(hr)) {
- qWarning()<<"failed to get config on capture device";
+ if (m_surface && !m_surface->supportedPixelFormats(QAbstractVideoBuffer::NoHandle)
+ .contains(QVideoFrame::Format_RGB32)) {
+ qWarning() << "Video surface needs to support RGB32 pixel format";
return false;
}
- int iCount;
- int iSize;
- hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize);
- if(FAILED(hr)) {
- qWarning()<<"failed to get capabilities";
+ m_previewPixelFormat = QVideoFrame::Format_RGB32;
+ m_previewSize = m_sourcePreferredResolution;
+ m_previewSurfaceFormat = QVideoSurfaceFormat(m_previewSize,
+ m_previewPixelFormat,
+ QAbstractVideoBuffer::NoHandle);
+ m_previewSurfaceFormat.setScanLineDirection(QVideoSurfaceFormat::BottomToTop);
+
+ HRESULT hr;
+ IAMStreamConfig* pConfig = 0;
+ hr = m_graphBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
+ &MEDIATYPE_Video,
+ m_sourceFilter,
+ IID_IAMStreamConfig, (void**)&pConfig);
+ if (FAILED(hr)) {
+ qWarning() << "Failed to get config for capture device";
return false;
}
- bool setFormatOK = false;
- for (int iIndex = 0; iIndex < iCount; iIndex++) {
- hr = pConfig->GetStreamCaps(iIndex, &pmt, reinterpret_cast<BYTE*>(&scc));
- if (hr == S_OK) {
- pvi = (VIDEOINFOHEADER*)pmt->pbFormat;
+ hr = pConfig->SetFormat(&m_sourcePreferredFormat);
- if ((pmt->majortype == MEDIATYPE_Video) &&
- (pmt->formattype == FORMAT_VideoInfo)) {
- if ((actualFormat.frameWidth() == pvi->bmiHeader.biWidth) &&
- (actualFormat.frameHeight() == pvi->bmiHeader.biHeight)) {
- hr = pConfig->SetFormat(pmt);
- _FreeMediaType(*pmt);
- if(FAILED(hr)) {
- qWarning()<<"failed to set format:" << hr;
- qWarning()<<"but going to continue";
- continue; // We going to continue
- } else {
- setFormatOK = true;
- break;
- }
- }
- }
- }
- }
pConfig->Release();
- if (!setFormatOK) {
- qWarning() << "unable to set any format for camera";
- return false;
- }
-
- // Set Sample Grabber config to match capture
- ZeroMemory(&am_media_type, sizeof(am_media_type));
- am_media_type.majortype = MEDIATYPE_Video;
-
- if (actualFormat.pixelFormat() == QVideoFrame::Format_RGB32)
- am_media_type.subtype = MEDIASUBTYPE_RGB32;
- else if (actualFormat.pixelFormat() == QVideoFrame::Format_RGB24)
- am_media_type.subtype = MEDIASUBTYPE_RGB24;
- else if (actualFormat.pixelFormat() == QVideoFrame::Format_YUYV)
- am_media_type.subtype = MEDIASUBTYPE_YUY2;
- else if (actualFormat.pixelFormat() == QVideoFrame::Format_YUV420P)
- am_media_type.subtype = MEDIASUBTYPE_I420;
- else if (actualFormat.pixelFormat() == QVideoFrame::Format_RGB555)
- am_media_type.subtype = MEDIASUBTYPE_RGB555;
- else if (actualFormat.pixelFormat() == QVideoFrame::Format_UYVY)
- am_media_type.subtype = MEDIASUBTYPE_UYVY;
- else {
- qWarning()<<"unknown format? for SG";
+ if (FAILED(hr)) {
+ qWarning() << "Unable to set video format on capture device";
return false;
}
- am_media_type.formattype = FORMAT_VideoInfo;
- hr = pSG->SetMediaType(&am_media_type);
+ // Set sample grabber format (always RGB32)
+ AM_MEDIA_TYPE grabberFormat;
+ ZeroMemory(&grabberFormat, sizeof(grabberFormat));
+ grabberFormat.majortype = MEDIATYPE_Video;
+ grabberFormat.subtype = MEDIASUBTYPE_RGB32;
+ grabberFormat.formattype = FORMAT_VideoInfo;
+ hr = m_previewSampleGrabber->SetMediaType(&grabberFormat);
if (FAILED(hr)) {
- qWarning()<<"failed to set video format on grabber";
+ qWarning() << "Failed to set video format on grabber";
return false;
}
- pSG->GetConnectedMediaType(&StillMediaType);
-
- CoUninitialize();
-
return true;
}
-bool DSCameraSession::openStream()
+bool DSCameraSession::connectGraph()
{
- //Opens the stream for reading and allocates any necessary resources needed
- //Return true if success, false otherwise
-
- if (opened) {
- return true;
- }
-
- if (!graph) {
- graph = createFilterGraph();
- if(!graph) {
- qWarning()<<"failed to create filter graph in openStream";
- return false;
- }
+ HRESULT hr = m_filterGraph->AddFilter(m_sourceFilter, L"Capture Filter");
+ if (FAILED(hr)) {
+ qWarning() << "failed to add capture filter to graph";
+ return false;
}
- CoInitialize(NULL);
-
- HRESULT hr;
-
- hr = pGraph->AddFilter(pCap, L"Capture Filter");
+ hr = m_filterGraph->AddFilter(m_previewFilter, L"Sample Grabber");
if (FAILED(hr)) {
- qWarning()<<"failed to create capture filter";
+ qWarning() << "failed to add sample grabber to graph";
return false;
}
- hr = pGraph->AddFilter(pSG_Filter, L"Sample Grabber");
+ hr = m_filterGraph->AddFilter(m_nullRendererFilter, L"Null Renderer");
if (FAILED(hr)) {
- qWarning()<<"failed to add sample grabber";
+ qWarning() << "failed to add null renderer to graph";
return false;
}
- hr = pBuild->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
- pCap, NULL, pSG_Filter);
+ hr = m_graphBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
+ m_sourceFilter,
+ m_previewFilter,
+ m_nullRendererFilter);
if (FAILED(hr)) {
- qWarning() << "failed to renderstream" << hr;
+ qWarning() << "Graph failed to connect filters" << hr;
return false;
}
- pSG->GetConnectedMediaType(&StillMediaType);
- pSG_Filter->Release();
-
- CoUninitialize();
return true;
}
-void DSCameraSession::closeStream()
+void DSCameraSession::disconnectGraph()
{
- // Closes the stream and internally frees any resources used
- HRESULT hr;
- IMediaControl* pControl = 0;
-
- hr = pGraph->QueryInterface(IID_IMediaControl,(void**)&pControl);
- if (FAILED(hr)) {
- qWarning()<<"failed to get stream control";
- return;
+ IPin *pPin = 0;
+ HRESULT hr = getPin(m_sourceFilter, PINDIR_OUTPUT, &pPin);
+ if (SUCCEEDED(hr)) {
+ m_filterGraph->Disconnect(pPin);
+ pPin->Release();
+ pPin = NULL;
}
- hr = pControl->StopWhenReady();
- if (FAILED(hr)) {
- qWarning()<<"failed to stop";
- pControl->Release();
- return;
+ hr = getPin(m_previewFilter, PINDIR_INPUT, &pPin);
+ if (SUCCEEDED(hr)) {
+ m_filterGraph->Disconnect(pPin);
+ pPin->Release();
+ pPin = NULL;
}
- pControl->Release();
-
- opened = false;
- IPin *pPin = 0;
-
- if (pCap)
- {
- hr = getPin(pCap, PINDIR_OUTPUT, &pPin);
- if(FAILED(hr)) {
- qWarning()<<"failed to disconnect capture filter";
- return;
- }
+ hr = getPin(m_previewFilter, PINDIR_OUTPUT, &pPin);
+ if (SUCCEEDED(hr)) {
+ m_filterGraph->Disconnect(pPin);
+ pPin->Release();
+ pPin = NULL;
}
- pGraph->Disconnect(pPin);
- if (FAILED(hr)) {
- qWarning()<<"failed to disconnect grabber filter";
- return;
+ hr = getPin(m_nullRendererFilter, PINDIR_INPUT, &pPin);
+ if (SUCCEEDED(hr)) {
+ m_filterGraph->Disconnect(pPin);
+ pPin->Release();
+ pPin = NULL;
}
- hr = getPin(pSG_Filter,PINDIR_INPUT,&pPin);
- pGraph->Disconnect(pPin);
- pGraph->RemoveFilter(pSG_Filter);
- pGraph->RemoveFilter(pCap);
-
- SAFE_RELEASE(pCap);
- SAFE_RELEASE(pSG_Filter);
- SAFE_RELEASE(pGraph);
- SAFE_RELEASE(pBuild);
-
- graph = false;
+ m_filterGraph->RemoveFilter(m_nullRendererFilter);
+ m_filterGraph->RemoveFilter(m_previewFilter);
+ m_filterGraph->RemoveFilter(m_sourceFilter);
}
-bool DSCameraSession::startStream()
+void DSCameraSession::updateSourceCapabilities()
{
- // Starts the stream, by emitting either QVideoPackets
- // or QvideoFrames, depending on Format chosen
- if (!graph)
- graph = createFilterGraph();
-
- if (!setProperties()) {
- qWarning() << "Couldn't set properties (retrying)";
- closeStream();
- if (!openStream()) {
- qWarning() << "Retry to open strean failed";
- return false;
- }
- }
-
- if (!opened) {
- opened = openStream();
- if (!opened) {
- qWarning() << "failed to openStream()";
- return false;
- }
- }
-
HRESULT hr;
- IMediaControl* pControl = 0;
-
- hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);
- if (FAILED(hr)) {
- qWarning() << "failed to get stream control";
- return false;
- }
+ AM_MEDIA_TYPE *pmt = NULL;
+ VIDEOINFOHEADER *pvi = NULL;
+ VIDEO_STREAM_CONFIG_CAPS scc;
+ IAMStreamConfig* pConfig = 0;
- hr = pControl->Run();
- pControl->Release();
+ m_needsHorizontalMirroring = false;
+ m_sourcePreferredResolution = QSize();
+ _FreeMediaType(m_sourcePreferredFormat);
+ ZeroMemory(&m_sourcePreferredFormat, sizeof(m_sourcePreferredFormat));
+ IAMVideoControl *pVideoControl = 0;
+ hr = m_graphBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
+ m_sourceFilter,
+ IID_IAMVideoControl, (void**)&pVideoControl);
if (FAILED(hr)) {
- qWarning() << "failed to start";
- return false;
+ qWarning() << "Failed to get the video control";
+ } else {
+ IPin *pPin = 0;
+ hr = getPin(m_sourceFilter, PINDIR_OUTPUT, &pPin);
+ if (FAILED(hr)) {
+ qWarning() << "Failed to get the pin for the video control";
+ } else {
+ long supportedModes;
+ hr = pVideoControl->GetCaps(pPin, &supportedModes);
+ if (FAILED(hr)) {
+ qWarning() << "Failed to get the supported modes of the video control";
+ } else if (supportedModes & VideoControlFlag_FlipHorizontal) {
+ long mode;
+ hr = pVideoControl->GetMode(pPin, &mode);
+ if (FAILED(hr))
+ qWarning() << "Failed to get the mode of the video control";
+ else if (supportedModes & VideoControlFlag_FlipHorizontal)
+ m_needsHorizontalMirroring = (mode & VideoControlFlag_FlipHorizontal);
+ }
+ pPin->Release();
+ }
+ pVideoControl->Release();
}
- active = true;
- return true;
-}
-void DSCameraSession::stopStream()
-{
- // Stops the stream from emitting packets
- HRESULT hr;
-
- IMediaControl* pControl = 0;
- hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);
+ hr = m_graphBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
+ m_sourceFilter,
+ IID_IAMStreamConfig, (void**)&pConfig);
if (FAILED(hr)) {
- qWarning() << "failed to get stream control";
+ qWarning() << "failed to get config on capture device";
return;
}
- hr = pControl->Stop();
- pControl->Release();
+ int iCount;
+ int iSize;
+ hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize);
if (FAILED(hr)) {
- qWarning() << "failed to stop";
+ qWarning() << "failed to get capabilities";
return;
}
- active = false;
- if (opened) {
- closeStream();
+ // Use preferred pixel format (first in the list)
+ // Then, pick the highest available resolution among the typical resolutions
+ // used for camera preview.
+ if (commonPreviewResolutions->isEmpty())
+ populateCommonResolutions();
+
+ long maxPixelCount = 0;
+ for (int iIndex = 0; iIndex < iCount; ++iIndex) {
+ hr = pConfig->GetStreamCaps(iIndex, &pmt, reinterpret_cast<BYTE*>(&scc));
+ if (hr == S_OK) {
+ if ((pmt->majortype == MEDIATYPE_Video) &&
+ (pmt->formattype == FORMAT_VideoInfo) &&
+ (!m_sourcePreferredFormat.cbFormat ||
+ m_sourcePreferredFormat.subtype == pmt->subtype)) {
+
+ pvi = reinterpret_cast<VIDEOINFOHEADER*>(pmt->pbFormat);
+
+ QSize resolution(pvi->bmiHeader.biWidth, pvi->bmiHeader.biHeight);
+ long pixelCount = resolution.width() * resolution.height();
+
+ if (!m_sourcePreferredFormat.cbFormat ||
+ (pixelCount > maxPixelCount && commonPreviewResolutions->contains(resolution))) {
+ _FreeMediaType(m_sourcePreferredFormat);
+ _CopyMediaType(&m_sourcePreferredFormat, pmt);
+ m_sourcePreferredResolution = resolution;
+ maxPixelCount = pixelCount;
+ }
+ }
+ _FreeMediaType(*pmt);
+ }
}
+
+ pConfig->Release();
+
+ if (!m_sourcePreferredResolution.isValid())
+ m_sourcePreferredResolution = QSize(640, 480);
}
-void DSCameraSession::suspendStream()
+void DSCameraSession::populateCommonResolutions()
{
- // Pauses the stream
- HRESULT hr;
+ commonPreviewResolutions->append(QSize(1920, 1080)); // 1080p
+ commonPreviewResolutions->append(QSize(1280, 720)); // 720p
+ commonPreviewResolutions->append(QSize(1024, 576)); // WSVGA
+ commonPreviewResolutions->append(QSize(720, 480)); // 480p (16:9)
+ commonPreviewResolutions->append(QSize(640, 480)); // 480p (4:3)
+ commonPreviewResolutions->append(QSize(352, 288)); // CIF
+ commonPreviewResolutions->append(QSize(320, 240)); // QVGA
+}
- IMediaControl* pControl = 0;
- hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);
- if (FAILED(hr)) {
- qWarning() << "failed to get stream control";
- return;
- }
+HRESULT getPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin)
+{
+ *ppPin = 0;
+ IEnumPins *pEnum = 0;
+ IPin *pPin = 0;
- hr = pControl->Pause();
- pControl->Release();
+ HRESULT hr = pFilter->EnumPins(&pEnum);
if (FAILED(hr)) {
- qWarning() << "failed to pause";
- return;
+ return hr;
}
- active = false;
-}
-
-void DSCameraSession::resumeStream()
-{
- // Resumes a paused stream
- startStream();
+ pEnum->Reset();
+ while (pEnum->Next(1, &pPin, NULL) == S_OK) {
+ PIN_DIRECTION ThisPinDir;
+ pPin->QueryDirection(&ThisPinDir);
+ if (ThisPinDir == PinDir) {
+ pEnum->Release();
+ *ppPin = pPin;
+ return S_OK;
+ }
+ pPin->Release();
+ }
+ pEnum->Release();
+ return E_FAIL;
}
QT_END_NAMESPACE
-
diff --git a/src/plugins/directshow/camera/dscamerasession.h b/src/plugins/directshow/camera/dscamerasession.h
index 0fe12dec3..2ba9c6109 100644
--- a/src/plugins/directshow/camera/dscamerasession.h
+++ b/src/plugins/directshow/camera/dscamerasession.h
@@ -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();
-
- // 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);
+ QCamera::Status status() const { return m_status; }
- // media control
-
- bool setOutputLocation(const QUrl &sink);
- QUrl outputLocation() const;
- qint64 position() const;
- int state() const;
- void record();
- void pause();
- void stop();
+ void setDevice(const QString &device);
- void setSurface(QAbstractVideoSurface* surface);
+ bool load();
+ bool unload();
+ bool startPreview();
+ bool stopPreview();
+ bool isReadyForCapture();
int captureImage(const QString &fileName);
- AM_MEDIA_TYPE StillMediaType;
- QList<video_buffer*> frames;
- SampleGrabberCallbackPrivate* StillCapCB;
-
- QMutex mutex;
+ void setSurface(QAbstractVideoSurface* surface);
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;
-
- 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 setStatus(QCamera::Status status);
+ void populateCommonResolutions();
- ICaptureGraphBuilder2* pBuild;
- IGraphBuilder* pGraph;
- IBaseFilter* pCap;
- IBaseFilter* pSG_Filter;
- ISampleGrabber *pSG;
+ void onFrameAvailable(const char *frameData, long len);
+ void saveCapturedImage(int id, const QImage &image, const QString &path);
-
- 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
diff --git a/src/plugins/directshow/camera/dsimagecapturecontrol.cpp b/src/plugins/directshow/camera/dsimagecapturecontrol.cpp
index e689b13d1..329f6d63a 100644
--- a/src/plugins/directshow/camera/dsimagecapturecontrol.cpp
+++ b/src/plugins/directshow/camera/dsimagecapturecontrol.cpp
@@ -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
diff --git a/src/plugins/directshow/camera/dsimagecapturecontrol.h b/src/plugins/directshow/camera/dsimagecapturecontrol.h
index e39539191..af8765943 100644
--- a/src/plugins/directshow/camera/dsimagecapturecontrol.h
+++ b/src/plugins/directshow/camera/dsimagecapturecontrol.h
@@ -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
diff --git a/src/plugins/directshow/camera/dsvideodevicecontrol.cpp b/src/plugins/directshow/camera/dsvideodevicecontrol.cpp
index ead1060d4..28d4956dd 100644
--- a/src/plugins/directshow/camera/dsvideodevicecontrol.cpp
+++ b/src/plugins/directshow/camera/dsvideodevicecontrol.cpp
@@ -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)
diff --git a/src/plugins/directshow/camera/dsvideowidgetcontrol.cpp b/src/plugins/directshow/camera/dsvideowidgetcontrol.cpp
deleted file mode 100644
index 35b795546..000000000
--- a/src/plugins/directshow/camera/dsvideowidgetcontrol.cpp
+++ /dev/null
@@ -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
diff --git a/src/plugins/directshow/camera/dsvideowidgetcontrol.h b/src/plugins/directshow/camera/dsvideowidgetcontrol.h
deleted file mode 100644
index 2a8775aee..000000000
--- a/src/plugins/directshow/camera/dsvideowidgetcontrol.h
+++ /dev/null
@@ -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