Initial copy of QtMultimediaKit.

Comes from original repo, with SHA1:
2c82d5611655e5967f5c5095af50c0991c4378b2
This commit is contained in:
Michael Goddard
2011-06-29 13:38:46 +10:00
commit 2a34e88c1e
1048 changed files with 206259 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
INCLUDEPATH += $$PWD
DEFINES += QMEDIA_DIRECTSHOW_CAMERA
win32-g++: DEFINES += QT_NO_WMSDK
win32: DEFINES += _CRT_SECURE_NO_WARNINGS
HEADERS += \
$$PWD/dscameraservice.h \
$$PWD/dscameracontrol.h \
$$PWD/dsvideorenderer.h \
$$PWD/dsvideodevicecontrol.h \
$$PWD/dsimagecapturecontrol.h \
$$PWD/dscamerasession.h \
$$PWD/dsvideowidgetcontrol.h \
$$PWD/dscameraservice.h \
$$PWD/directshowglobal.h
SOURCES += \
$$PWD/dscameraservice.cpp \
$$PWD/dscameracontrol.cpp \
$$PWD/dsvideorenderer.cpp \
$$PWD/dsvideodevicecontrol.cpp \
$$PWD/dsimagecapturecontrol.cpp \
$$PWD/dscamerasession.cpp \
$$PWD/dsvideowidgetcontrol.cpp
INCLUDEPATH += $(DXSDK_DIR)/include
LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32

View File

@@ -0,0 +1,236 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DIRECTSHOWGLOBAL_H
#define DIRECTSHOWGLOBAL_H
#include <QtCore/qglobal.h>
#include <dshow.h>
DEFINE_GUID(MEDIASUBTYPE_I420,
0x30323449,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71);
extern const GUID MEDIASUBTYPE_RGB24;
extern const GUID MEDIASUBTYPE_RGB32;
extern const GUID MEDIASUBTYPE_YUY2;
extern const GUID MEDIASUBTYPE_MJPG;
extern const GUID MEDIASUBTYPE_RGB555;
extern const GUID MEDIASUBTYPE_YVU9;
extern const GUID MEDIASUBTYPE_UYVY;
extern const GUID PIN_CATEGORY_CAPTURE;
extern const GUID PIN_CATEGORY_PREVIEW;
extern const IID IID_IPropertyBag;
extern const IID IID_ISampleGrabber;
extern const IID IID_ICaptureGraphBuilder2;
extern const IID IID_IAMStreamConfig;
extern const CLSID CLSID_CVidCapClassManager;
extern const CLSID CLSID_VideoInputDeviceCategory;
extern const CLSID CLSID_SampleGrabber;
extern const CLSID CLSID_CaptureGraphBuilder2;
#define SAFE_RELEASE(x) { if(x) x->Release(); x = NULL; }
typedef struct IFileSinkFilter *LPFILESINKFILTER;
typedef struct IAMCopyCaptureFileProgress *LPAMCOPYCAPTUREFILEPROGRESS;
#ifndef __ICaptureGraphBuilder2_INTERFACE_DEFINED__
#define __ICaptureGraphBuilder2_INTERFACE_DEFINED__
struct ICaptureGraphBuilder2 : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE SetFiltergraph(
/* [in] */ IGraphBuilder *pfg) = 0;
virtual HRESULT STDMETHODCALLTYPE GetFiltergraph(
/* [out] */ IGraphBuilder **ppfg) = 0;
virtual HRESULT STDMETHODCALLTYPE SetOutputFileName(
/* [in] */ const GUID *pType,
/* [in] */ LPCOLESTR lpstrFile,
/* [out] */ IBaseFilter **ppf,
/* [out] */ IFileSinkFilter **ppSink) = 0;
virtual /* [local] */ HRESULT STDMETHODCALLTYPE FindInterface(
/* [in] */ const GUID *pCategory,
/* [in] */ const GUID *pType,
/* [in] */ IBaseFilter *pf,
/* [in] */ REFIID riid,
/* [out] */ void **ppint) = 0;
virtual HRESULT STDMETHODCALLTYPE RenderStream(
/* [in] */ const GUID *pCategory,
/* [in] */ const GUID *pType,
/* [in] */ IUnknown *pSource,
/* [in] */ IBaseFilter *pfCompressor,
/* [in] */ IBaseFilter *pfRenderer) = 0;
virtual HRESULT STDMETHODCALLTYPE ControlStream(
/* [in] */ const GUID *pCategory,
/* [in] */ const GUID *pType,
/* [in] */ IBaseFilter *pFilter,
/* [in] */ REFERENCE_TIME *pstart,
/* [in] */ REFERENCE_TIME *pstop,
/* [in] */ WORD wStartCookie,
/* [in] */ WORD wStopCookie) = 0;
virtual HRESULT STDMETHODCALLTYPE AllocCapFile(
/* [in] */ LPCOLESTR lpstr,
/* [in] */ DWORDLONG dwlSize) = 0;
virtual HRESULT STDMETHODCALLTYPE CopyCaptureFile(
/* [in] */ LPOLESTR lpwstrOld,
/* [in] */ LPOLESTR lpwstrNew,
/* [in] */ int fAllowEscAbort,
/* [in] */ IAMCopyCaptureFileProgress *pCallback) = 0;
virtual HRESULT STDMETHODCALLTYPE FindPin(
/* [in] */ IUnknown *pSource,
/* [in] */ PIN_DIRECTION pindir,
/* [in] */ const GUID *pCategory,
/* [in] */ const GUID *pType,
/* [in] */ BOOL fUnconnected,
/* [in] */ int num,
/* [out] */ IPin **ppPin) = 0;
};
#endif
#ifndef __IAMStreamConfig_INTERFACE_DEFINED__
#define __IAMStreamConfig_INTERFACE_DEFINED__
struct IAMStreamConfig : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE SetFormat(
/* [in] */ AM_MEDIA_TYPE *pmt) = 0;
virtual HRESULT STDMETHODCALLTYPE GetFormat(
/* [out] */ AM_MEDIA_TYPE **ppmt) = 0;
virtual HRESULT STDMETHODCALLTYPE GetNumberOfCapabilities(
/* [out] */ int *piCount,
/* [out] */ int *piSize) = 0;
virtual HRESULT STDMETHODCALLTYPE GetStreamCaps(
/* [in] */ int iIndex,
/* [out] */ AM_MEDIA_TYPE **ppmt,
/* [out] */ BYTE *pSCC) = 0;
};
#endif
#ifndef __IErrorLog_INTERFACE_DEFINED__
#define __IErrorLog_INTERFACE_DEFINED__
struct IErrorLog : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE AddError(
/* [in] */ LPCOLESTR pszPropName,
/* [in] */ EXCEPINFO *pExcepInfo) = 0;
};
#endif
#ifndef __IPropertyBag_INTERFACE_DEFINED__
#define __IPropertyBag_INTERFACE_DEFINED__
struct IPropertyBag : public IUnknown
{
public:
virtual /* [local] */ HRESULT STDMETHODCALLTYPE Read(
/* [in] */ LPCOLESTR pszPropName,
/* [out][in] */ VARIANT *pVar,
/* [in] */ IErrorLog *pErrorLog) = 0;
virtual HRESULT STDMETHODCALLTYPE Write(
/* [in] */ LPCOLESTR pszPropName,
/* [in] */ VARIANT *pVar) = 0;
};
#endif
typedef struct IMediaSample *LPMEDIASAMPLE;
EXTERN_C const IID IID_ISampleGrabberCB;
#ifndef __ISampleGrabberCB_INTERFACE_DEFINED__
#define __ISampleGrabberCB_INTERFACE_DEFINED__
#undef INTERFACE
#define INTERFACE ISampleGrabberCB
DECLARE_INTERFACE_(ISampleGrabberCB, IUnknown)
{
// STDMETHOD(QueryInterface) (THIS_ const GUID *, void **) PURE;
STDMETHOD(QueryInterface) (THIS_ REFIID riid, void **) PURE;
STDMETHOD_(ULONG, AddRef) (THIS) PURE;
STDMETHOD_(ULONG, Release) (THIS) PURE;
STDMETHOD_(HRESULT, SampleCB) (THIS_ double, LPMEDIASAMPLE) PURE;
STDMETHOD_(HRESULT, BufferCB) (THIS_ double, BYTE *, long) PURE;
};
#undef INTERFACE
#endif
#ifndef __ISampleGrabber_INTERFACE_DEFINED__
#define __ISampleGrabber_INTERFACE_DEFINED__
#define INTERFACE ISampleGrabber
DECLARE_INTERFACE_(ISampleGrabber,IUnknown)
{
STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
STDMETHOD(SetOneShot)(THIS_ BOOL) PURE;
STDMETHOD(SetMediaType)(THIS_ const AM_MEDIA_TYPE*) PURE;
STDMETHOD(GetConnectedMediaType)(THIS_ AM_MEDIA_TYPE*) PURE;
STDMETHOD(SetBufferSamples)(THIS_ BOOL) PURE;
STDMETHOD(GetCurrentBuffer)(THIS_ long*,long*) PURE;
STDMETHOD(GetCurrentSample)(THIS_ IMediaSample**) PURE;
STDMETHOD(SetCallback)(THIS_ ISampleGrabberCB *,long) PURE;
};
#undef INTERFACE
#endif
#endif

View File

@@ -0,0 +1,103 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/qdebug.h>
#include "dscameracontrol.h"
#include "dscameraservice.h"
#include "dscamerasession.h"
QT_BEGIN_NAMESPACE
DSCameraControl::DSCameraControl(QObject *parent)
:QCameraControl(parent), m_captureMode(QCamera::CaptureStillImage)
{
m_session = qobject_cast<DSCameraSession*>(parent);
connect(m_session, SIGNAL(stateChanged(QCamera::State)),this, SIGNAL(stateChanged(QCamera::State)));
}
DSCameraControl::~DSCameraControl()
{
}
void DSCameraControl::setState(QCamera::State state)
{
switch (state) {
case QCamera::ActiveState:
start();
break;
case QCamera::UnloadedState: /* fall through */
case QCamera::LoadedState:
stop();
break;
}
}
bool DSCameraControl::isCaptureModeSupported(QCamera::CaptureMode mode) const
{
bool bCaptureSupported = false;
switch (mode) {
case QCamera::CaptureStillImage:
bCaptureSupported = true;
break;
case QCamera::CaptureVideo:
bCaptureSupported = false;
break;
}
return bCaptureSupported;
}
void DSCameraControl::start()
{
m_session->record();
}
void DSCameraControl::stop()
{
m_session->stop();
}
QCamera::State DSCameraControl::state() const
{
return (QCamera::State)m_session->state();
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,94 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DSCAMERACONTROL_H
#define DSCAMERACONTROL_H
#include <QtCore/qobject.h>
#include <qcameracontrol.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class DSCameraService;
class DSCameraSession;
class DSCameraControl : public QCameraControl
{
Q_OBJECT
public:
DSCameraControl(QObject *parent = 0);
~DSCameraControl();
void start();
void stop();
QCamera::State state() const;
QCamera::CaptureMode captureMode() const { return m_captureMode; }
void setCaptureMode(QCamera::CaptureMode mode)
{
if (m_captureMode != mode) {
m_captureMode = mode;
emit captureModeChanged(mode);
}
}
void setState(QCamera::State state);
QCamera::Status status() const { return QCamera::UnavailableStatus; }
bool isCaptureModeSupported(QCamera::CaptureMode mode) const;
bool canChangeProperty(PropertyChangeType /* changeType */, QCamera::Status /* status */) const {return false; }
private:
DSCameraSession *m_session;
DSCameraService *m_service;
QCamera::CaptureMode m_captureMode;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

View File

@@ -0,0 +1,114 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/qvariant.h>
#include <QtCore/qdebug.h>
#include <QtGui/qwidget.h>
#include <QVideoWidgetControl.h>
#include "dscameraservice.h"
#include "dscameracontrol.h"
#include "dscamerasession.h"
#include "dsvideorenderer.h"
#include "dsvideodevicecontrol.h"
#include "dsimagecapturecontrol.h"
#include "dsvideowidgetcontrol.h"
QT_BEGIN_NAMESPACE
DSCameraService::DSCameraService(QObject *parent):
QMediaService(parent)
{
m_session = new DSCameraSession(this);
m_control = new DSCameraControl(m_session);
m_videoDevice = new DSVideoDeviceControl(m_session);
m_videoRenderer = new DSVideoRendererControl(m_session, this);
m_imageCapture = new DSImageCaptureControl(m_session);
m_viewFinderWidget = new DSVideoWidgetControl(m_session);
m_device = QByteArray("default");
}
DSCameraService::~DSCameraService()
{
delete m_control;
delete m_videoDevice;
delete m_videoRenderer;
delete m_imageCapture;
delete m_viewFinderWidget;
delete m_session;
}
QMediaControl* DSCameraService::requestControl(const char *name)
{
if(qstrcmp(name,QCameraControl_iid) == 0)
return m_control;
if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0)
return m_imageCapture;
if (qstrcmp(name, QVideoWidgetControl_iid) == 0) {
if (m_viewFinderWidget) {
return m_viewFinderWidget;
}
}
if(qstrcmp(name,QVideoRendererControl_iid) == 0)
return m_videoRenderer;
if(qstrcmp(name,QVideoDeviceControl_iid) == 0)
return m_videoDevice;
return 0;
}
void DSCameraService::releaseControl(QMediaControl *control)
{
// Implemented as a singleton, so we do nothing.
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,88 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DSCAMERASERVICE_H
#define DSCAMERASERVICE_H
#include <QtCore/qobject.h>
#include <qmediaservice.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class DSCameraControl;
class DSCameraSession;
class DSVideoOutputControl;
class DSVideoDeviceControl;
class DSVideoRendererControl;
class DSImageCaptureControl;
class DSVideoWidgetControl;
class DSCameraService : public QMediaService
{
Q_OBJECT
public:
DSCameraService(QObject *parent = 0);
~DSCameraService();
virtual QMediaControl* requestControl(const char *name);
virtual void releaseControl(QMediaControl *control);
private:
DSCameraControl *m_control;
DSCameraSession *m_session;
DSVideoOutputControl *m_videoOutput;
DSVideoWidgetControl *m_viewFinderWidget;
DSVideoDeviceControl *m_videoDevice;
DSVideoRendererControl *m_videoRenderer;
DSImageCaptureControl *m_imageCapture;
QByteArray m_device;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,208 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DSCAMERASESSION_H
#define DSCAMERASESSION_H
#include <QtCore/qobject.h>
#include <QTime>
#include <QUrl>
#include <QMutex>
#include <qcamera.h>
#include <QtMultimedia/qvideoframe.h>
#include <QtMultimedia/qabstractvideosurface.h>
#include <QtMultimedia/qvideosurfaceformat.h>
#include <tchar.h>
#include <dshow.h>
#include <objbase.h>
#include <initguid.h>
#pragma comment(lib, "strmiids.lib")
#pragma comment(lib, "ole32.lib")
#include <windows.h>
#pragma include_alias("dxtrans.h","qedit.h")
#define __IDxtCompositor_INTERFACE_DEFINED__
#define __IDxtAlphaSetter_INTERFACE_DEFINED__
#define __IDxtJpeg_INTERFACE_DEFINED__
#define __IDxtKey_INTERFACE_DEFINED__
#include <qedit.h>
struct ICaptureGraphBuilder2;
struct ISampleGrabber;
QT_BEGIN_HEADER
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
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);
// media control
bool setOutputLocation(const QUrl &sink);
QUrl outputLocation() const;
qint64 position() const;
int state() const;
void record();
void pause();
void stop();
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 imageCaptured(int id, const QImage &preview);
void imageSaved(int id, const QString &fileName);
void readyForCaptureChanged(bool);
private Q_SLOTS:
void captureFrame();
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;
ICaptureGraphBuilder2* pBuild;
IGraphBuilder* pGraph;
IBaseFilter* pCap;
IBaseFilter* pSG_Filter;
ISampleGrabber *pSG;
QString m_snapshot;
int m_currentImageId;
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();
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

View File

@@ -0,0 +1,83 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/QDebug>
#include "dsimagecapturecontrol.h"
QT_BEGIN_NAMESPACE
DSImageCaptureControl::DSImageCaptureControl(DSCameraSession *session)
:QCameraImageCaptureControl(session), m_session(session), m_ready(false)
{
connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(updateState()));
connect(m_session, SIGNAL(imageCaptured(const int, QImage)),
this, SIGNAL(imageCaptured(const int, QImage)));
connect(m_session, SIGNAL(imageSaved(const int, const QString &)),
this, SIGNAL(imageSaved(const int, const QString &)));
connect(m_session, SIGNAL(readyForCaptureChanged(bool)),
this, SIGNAL(readyForCaptureChanged(bool)));
}
DSImageCaptureControl::~DSImageCaptureControl()
{
}
bool DSImageCaptureControl::isReadyForCapture() const
{
return m_ready;
}
int DSImageCaptureControl::capture(const QString &fileName)
{
return m_session->captureImage(fileName);
}
void DSImageCaptureControl::updateState()
{
bool ready = (m_session->state() == QCamera::ActiveState) &&
!m_session->pictureInProgress();
if(m_ready != ready)
emit readyForCaptureChanged(m_ready = ready);
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,80 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DSIMAGECAPTURECONTROL_H
#define DSIMAGECAPTURECONTROL_H
#include <qcameraimagecapturecontrol.h>
#include "dscamerasession.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class DSImageCaptureControl : public QCameraImageCaptureControl
{
Q_OBJECT
public:
DSImageCaptureControl(DSCameraSession *session);
virtual ~DSImageCaptureControl();
bool isReadyForCapture() const;
int capture(const QString &fileName);
virtual QCameraImageCapture::DriveMode driveMode() const { return QCameraImageCapture::SingleImageCapture; }
virtual void setDriveMode(QCameraImageCapture::DriveMode mode) { }
virtual void cancelCapture() {}
private slots:
void updateState();
private:
DSCameraSession *m_session;
bool m_ready;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // DSCAPTURECONTROL_H

View File

@@ -0,0 +1,168 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QDebug>
#include <QFile>
#include <QtGui/QIcon>
#include "dsvideodevicecontrol.h"
#include "dscamerasession.h"
#include <tchar.h>
#include <dshow.h>
#include <objbase.h>
#include <initguid.h>
#include <Ocidl.h>
#include <string.h>
extern const CLSID CLSID_VideoInputDeviceCategory;
QT_BEGIN_NAMESPACE
DSVideoDeviceControl::DSVideoDeviceControl(QObject *parent)
: QVideoDeviceControl(parent)
{
m_session = qobject_cast<DSCameraSession*>(parent);
devices.clear();
descriptions.clear();
CoInitialize(NULL);
ICreateDevEnum* pDevEnum = NULL;
IEnumMoniker* pEnum = NULL;
// 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;
while(pEnum->Next(1, &pMoniker, NULL) == S_OK) {
IPropertyBag *pPropBag;
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
(void**)(&pPropBag));
if(FAILED(hr)) {
pMoniker->Release();
continue; // skip this one
}
// Find the description
WCHAR str[120];
VARIANT varName;
varName.vt = VT_BSTR;
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
if(SUCCEEDED(hr)) {
wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0]));
QString temp(QString::fromUtf16((unsigned short*)str));
devices.append(QString("ds:%1").arg(temp).toLocal8Bit().constData());
hr = pPropBag->Read(L"Description", &varName, 0);
wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0]));
QString temp2(QString::fromUtf16((unsigned short*)str));
descriptions.append(temp2.toLocal8Bit().constData());
}
pPropBag->Release();
pMoniker->Release();
}
pEnum->Release();
}
pDevEnum->Release();
}
CoUninitialize();
selected = 0;
}
int DSVideoDeviceControl::deviceCount() const
{
return devices.count();
}
QString DSVideoDeviceControl::deviceName(int index) const
{
if(index >= 0 && index <= devices.count())
return devices.at(index);
return QString();
}
QString DSVideoDeviceControl::deviceDescription(int index) const
{
if(index >= 0 && index <= descriptions.count())
return descriptions.at(index);
return QString();
}
QIcon DSVideoDeviceControl::deviceIcon(int index) const
{
Q_UNUSED(index)
return QIcon();
}
int DSVideoDeviceControl::defaultDevice() const
{
return 0;
}
int DSVideoDeviceControl::selectedDevice() const
{
return selected;
}
void DSVideoDeviceControl::setSelectedDevice(int index)
{
if(index >= 0 && index <= devices.count()) {
if (m_session) {
QString device = devices.at(index);
if (device.startsWith("ds:"))
device.remove(0,3);
m_session->setDevice(device);
}
selected = index;
}
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,83 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DSVIDEODEVICECONTROL_H
#define DSVIDEODEVICECONTROL_H
#include <qvideodevicecontrol.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class DSCameraSession;
//QTM_USE_NAMESPACE
class DSVideoDeviceControl : public QVideoDeviceControl
{
Q_OBJECT
public:
DSVideoDeviceControl(QObject *parent = 0);
int deviceCount() const;
QString deviceName(int index) const;
QString deviceDescription(int index) const;
QIcon deviceIcon(int index) const;
int defaultDevice() const;
int selectedDevice() const;
public Q_SLOTS:
void setSelectedDevice(int index);
private:
DSCameraSession* m_session;
QList<QString> devices;
QList<QString> descriptions;
int selected;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

View File

@@ -0,0 +1,72 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/qdebug.h>
#include "dsvideorenderer.h"
QT_BEGIN_NAMESPACE
DSVideoRendererControl::DSVideoRendererControl(DSCameraSession* session, QObject *parent)
:QVideoRendererControl(parent),
m_surface(0),
m_session(session)
{
}
DSVideoRendererControl::~DSVideoRendererControl()
{
}
QAbstractVideoSurface* DSVideoRendererControl::surface() const
{
return m_surface;
}
void DSVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
{
m_surface = surface;
if(m_session)
m_session->setSurface(m_surface);
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,77 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DSVIDEORENDERER_H
#define DSVIDEORENDERER_H
#include <qvideorenderercontrol.h>
#include "dscamerasession.h"
class CameraFormatConverter;
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class DSVideoRendererControl : public QVideoRendererControl
{
Q_OBJECT
public:
DSVideoRendererControl(DSCameraSession* session, QObject *parent = 0);
~DSVideoRendererControl();
QAbstractVideoSurface *surface() const;
void setSurface(QAbstractVideoSurface *surface);
void setSession(DSCameraSession* session);
private:
QAbstractVideoSurface* m_surface;
DSCameraSession* m_session;
CameraFormatConverter* converter;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // DSVIDEORENDERER_H

View File

@@ -0,0 +1,250 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $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)
{
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)
{
}
DSVideoWidgetControl::DSVideoWidgetControl(DSCameraSession* session, QObject *parent) :
m_session(session), QVideoWidgetControl(parent),
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

@@ -0,0 +1,154 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DSVIDEOWIDGETCONTROL_H
#define DSVIDEOWIDGETCONTROL_H
#include <QtCore/qobject.h>
#include <QtGui>
#include <QtMultimedia/qvideoframe.h>
#include <QtMultimedia/qabstractvideosurface.h>
#include <QtMultimedia/qvideosurfaceformat.h>
#include <qvideowidgetcontrol.h>
#include "DsCameraControl.h"
QT_BEGIN_HEADER
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
QT_END_HEADER
#endif // DSVideoWidgetControl_H

View File

@@ -0,0 +1,23 @@
TEMPLATE = lib
CONFIG += plugin
TARGET = $$qtLibraryTarget(dsengine)
PLUGIN_TYPE=mediaservice
include (../../../common.pri)
INCLUDEPATH+=../../multimediakit \
../../multimediakit/audio \
../../multimediakit/video
qtAddLibrary(QtMultimediaKit)
DEPENDPATH += .
HEADERS += dsserviceplugin.h
SOURCES += dsserviceplugin.cpp
!contains(wmsdk_enabled, yes): DEFINES += QT_NO_WMSDK
include (player/player.pri)
include (camera/camera.pri)

View File

@@ -0,0 +1,211 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/qstring.h>
#include <QtCore/qdebug.h>
#include <QtCore/QFile>
#include "dsserviceplugin.h"
#ifdef QMEDIA_DIRECTSHOW_CAMERA
#include "dscameraservice.h"
#endif
#ifdef QMEDIA_DIRECTSHOW_PLAYER
#include "directshowplayerservice.h"
#endif
#include <qmediaserviceprovider.h>
#ifdef QMEDIA_DIRECTSHOW_CAMERA
extern const CLSID CLSID_VideoInputDeviceCategory;
#ifndef _STRSAFE_H_INCLUDED_
#include <tchar.h>
#endif
#include <dshow.h>
#include <objbase.h>
#include <initguid.h>
#pragma comment(lib, "strmiids.lib")
#pragma comment(lib, "ole32.lib")
#include <windows.h>
#include <ocidl.h>
#endif
QT_USE_NAMESPACE
QStringList DSServicePlugin::keys() const
{
return QStringList()
#ifdef QMEDIA_DIRECTSHOW_CAMERA
<< QLatin1String(Q_MEDIASERVICE_CAMERA)
#endif
#ifdef QMEDIA_DIRECTSHOW_PLAYER
<< QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)
#endif
;
}
QMediaService* DSServicePlugin::create(QString const& key)
{
#ifdef QMEDIA_DIRECTSHOW_CAMERA
if (key == QLatin1String(Q_MEDIASERVICE_CAMERA))
return new DSCameraService;
#endif
#ifdef QMEDIA_DIRECTSHOW_PLAYER
if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER))
return new DirectShowPlayerService;
#endif
qDebug() << "unsupported key:" << key;
return 0;
}
void DSServicePlugin::release(QMediaService *service)
{
delete service;
}
QMediaServiceProviderHint::Features DSServicePlugin::supportedFeatures(
const QByteArray &service) const
{
if (service == Q_MEDIASERVICE_MEDIAPLAYER)
return QMediaServiceProviderHint::StreamPlayback | QMediaServiceProviderHint::VideoSurface;
else
return QMediaServiceProviderHint::Features();
}
QList<QByteArray> DSServicePlugin::devices(const QByteArray &service) const
{
#ifdef QMEDIA_DIRECTSHOW_CAMERA
if (service == Q_MEDIASERVICE_CAMERA) {
if (m_cameraDevices.isEmpty())
updateDevices();
return m_cameraDevices;
}
#endif
return QList<QByteArray>();
}
QString DSServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
{
#ifdef QMEDIA_DIRECTSHOW_CAMERA
if (service == Q_MEDIASERVICE_CAMERA) {
if (m_cameraDevices.isEmpty())
updateDevices();
for (int i=0; i<m_cameraDevices.count(); i++)
if (m_cameraDevices[i] == device)
return m_cameraDescriptions[i];
}
#endif
return QString();
}
#ifdef QMEDIA_DIRECTSHOW_CAMERA
void DSServicePlugin::updateDevices() const
{
m_cameraDevices.clear();
m_cameraDescriptions.clear();
BOOL bFound = TRUE;
CoInitialize(NULL);
ICreateDevEnum* pDevEnum = NULL;
IEnumMoniker* pEnum = NULL;
// 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;
while(pEnum->Next(1, &pMoniker, NULL) == S_OK) {
IPropertyBag *pPropBag;
hr = pMoniker->BindToStorage(0,0,IID_IPropertyBag,
(void**)(&pPropBag));
if(FAILED(hr)) {
pMoniker->Release();
continue; // skip this one
}
bFound = TRUE;
// Find the description
WCHAR str[120];
VARIANT varName;
varName.vt = VT_BSTR;
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
if(SUCCEEDED(hr)) {
wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0]));
QString temp(QString::fromUtf16((unsigned short*)str));
m_cameraDevices.append(QString("ds:%1").arg(temp).toLocal8Bit().constData());
hr = pPropBag->Read(L"Description", &varName, 0);
wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0]));
QString temp2(QString::fromUtf16((unsigned short*)str));
m_cameraDescriptions.append(temp2);
} else {
qWarning() << "No friendly name";
}
pPropBag->Release();
pMoniker->Release();
}
pEnum->Release();
}
pDevEnum->Release();
}
CoUninitialize();
if (!bFound) {
qWarning() << "No camera devices found";
}
}
#endif
Q_EXPORT_PLUGIN2(qtmedia_dsengine, DSServicePlugin);

View File

@@ -0,0 +1,76 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DSSERVICEPLUGIN_H
#define DSSERVICEPLUGIN_H
#include "qmediaserviceproviderplugin.h"
QT_USE_NAMESPACE
class DSServicePlugin
: public QMediaServiceProviderPlugin
, public QMediaServiceSupportedDevicesInterface
, public QMediaServiceFeaturesInterface
{
Q_OBJECT
Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
Q_INTERFACES(QMediaServiceFeaturesInterface)
public:
QStringList keys() const;
QMediaService* create(QString const& key);
void release(QMediaService *service);
QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const;
QList<QByteArray> devices(const QByteArray &service) const;
QString deviceDescription(const QByteArray &service, const QByteArray &device);
private:
#ifdef QMEDIA_DIRECTSHOW_CAMERA
void updateDevices() const;
mutable QList<QByteArray> m_cameraDevices;
mutable QStringList m_cameraDescriptions;
#endif
};
#endif // DSSERVICEPLUGIN_H

View File

@@ -0,0 +1,161 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "directshowaudioendpointcontrol.h"
#include "directshowglobal.h"
#include "directshowplayerservice.h"
DirectShowAudioEndpointControl::DirectShowAudioEndpointControl(
DirectShowPlayerService *service, QObject *parent)
: QAudioEndpointSelector(parent)
, m_service(service)
, m_bindContext(0)
, m_deviceEnumerator(0)
{
if (CreateBindCtx(0, &m_bindContext) == S_OK) {
m_deviceEnumerator = com_new<ICreateDevEnum>(CLSID_SystemDeviceEnum, IID_ICreateDevEnum);
updateEndpoints();
setActiveEndpoint(m_defaultEndpoint);
}
}
DirectShowAudioEndpointControl::~DirectShowAudioEndpointControl()
{
foreach (IMoniker *moniker, m_devices)
moniker->Release();
if (m_bindContext)
m_bindContext->Release();
if (m_deviceEnumerator)
m_deviceEnumerator->Release();
}
QList<QString> DirectShowAudioEndpointControl::availableEndpoints() const
{
return m_devices.keys();
}
QString DirectShowAudioEndpointControl::endpointDescription(const QString &name) const
{
#ifdef __IPropertyBag_INTERFACE_DEFINED__
QString description;
if (IMoniker *moniker = m_devices.value(name, 0)) {
IPropertyBag *propertyBag = 0;
if (SUCCEEDED(moniker->BindToStorage(
0, 0, IID_IPropertyBag, reinterpret_cast<void **>(&propertyBag)))) {
VARIANT name;
VariantInit(&name);
if (SUCCEEDED(propertyBag->Read(L"FriendlyName", &name, 0)))
description = QString::fromWCharArray(name.bstrVal);
VariantClear(&name);
propertyBag->Release();
}
}
return description;
#else
return name.section(QLatin1Char('\\'), -1);
#endif
}
QString DirectShowAudioEndpointControl::defaultEndpoint() const
{
return m_defaultEndpoint;
}
QString DirectShowAudioEndpointControl::activeEndpoint() const
{
return m_activeEndpoint;
}
void DirectShowAudioEndpointControl::setActiveEndpoint(const QString &name)
{
if (m_activeEndpoint == name)
return;
if (IMoniker *moniker = m_devices.value(name, 0)) {
IBaseFilter *filter = 0;
if (moniker->BindToObject(
m_bindContext,
0,
IID_IBaseFilter,
reinterpret_cast<void **>(&filter)) == S_OK) {
m_service->setAudioOutput(filter);
filter->Release();
}
}
}
void DirectShowAudioEndpointControl::updateEndpoints()
{
IMalloc *oleMalloc = 0;
if (m_deviceEnumerator && CoGetMalloc(1, &oleMalloc) == S_OK) {
IEnumMoniker *monikers = 0;
if (m_deviceEnumerator->CreateClassEnumerator(
CLSID_AudioRendererCategory, &monikers, 0) == S_OK) {
for (IMoniker *moniker = 0; monikers->Next(1, &moniker, 0) == S_OK; moniker->Release()) {
OLECHAR *string = 0;
if (moniker->GetDisplayName(m_bindContext, 0, &string) == S_OK) {
QString deviceId = QString::fromWCharArray(string);
oleMalloc->Free(string);
moniker->AddRef();
m_devices.insert(deviceId, moniker);
if (m_defaultEndpoint.isEmpty()
|| deviceId.endsWith(QLatin1String("Default DirectSound Device"))) {
m_defaultEndpoint = deviceId;
}
}
}
monikers->Release();
}
oleMalloc->Release();
}
}

View File

@@ -0,0 +1,82 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DIRECTSHOWAUDIOENDPOINTCONTROL_H
#define DIRECTSHOWAUDIOENDPOINTCONTROL_H
#include "qaudioendpointselector.h"
#include <dshow.h>
class DirectShowPlayerService;
QT_USE_NAMESPACE
class DirectShowAudioEndpointControl : public QAudioEndpointSelector
{
Q_OBJECT
public:
DirectShowAudioEndpointControl(DirectShowPlayerService *service, QObject *parent = 0);
~DirectShowAudioEndpointControl();
QList<QString> availableEndpoints() const;
QString endpointDescription(const QString &name) const;
QString defaultEndpoint() const;
QString activeEndpoint() const;
void setActiveEndpoint(const QString& name);
private:
void updateEndpoints();
DirectShowPlayerService *m_service;
IBindCtx *m_bindContext;
ICreateDevEnum *m_deviceEnumerator;
QMap<QString, IMoniker *> m_devices;
QString m_defaultEndpoint;
QString m_activeEndpoint;
};
#endif

View File

@@ -0,0 +1,150 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <directshoweventloop.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qcoreevent.h>
class DirectShowPostedEvent
{
public:
DirectShowPostedEvent(QObject *receiver, QEvent *event)
: receiver(receiver)
, event(event)
, next(0)
{
}
~DirectShowPostedEvent()
{
delete event;
}
QObject *receiver;
QEvent *event;
DirectShowPostedEvent *next;
};
DirectShowEventLoop::DirectShowEventLoop(QObject *parent)
: QObject(parent)
, m_postsHead(0)
, m_postsTail(0)
, m_eventHandle(::CreateEvent(0, 0, 0, 0))
, m_waitHandle(::CreateEvent(0, 0, 0, 0))
{
}
DirectShowEventLoop::~DirectShowEventLoop()
{
::CloseHandle(m_eventHandle);
::CloseHandle(m_waitHandle);
for (DirectShowPostedEvent *post = m_postsHead; post; post = m_postsHead) {
m_postsHead = m_postsHead->next;
delete post;
}
}
void DirectShowEventLoop::wait(QMutex *mutex)
{
::ResetEvent(m_waitHandle);
mutex->unlock();
HANDLE handles[] = { m_eventHandle, m_waitHandle };
while (::WaitForMultipleObjects(2, handles, false, INFINITE) == WAIT_OBJECT_0)
processEvents();
mutex->lock();
}
void DirectShowEventLoop::wake()
{
::SetEvent(m_waitHandle);
}
void DirectShowEventLoop::postEvent(QObject *receiver, QEvent *event)
{
QMutexLocker locker(&m_mutex);
DirectShowPostedEvent *post = new DirectShowPostedEvent(receiver, event);
if (m_postsTail)
m_postsTail->next = post;
else
m_postsHead = post;
m_postsTail = post;
QCoreApplication::postEvent(this, new QEvent(QEvent::User));
::SetEvent(m_eventHandle);
}
void DirectShowEventLoop::customEvent(QEvent *event)
{
if (event->type() == QEvent::User) {
processEvents();
} else {
QObject::customEvent(event);
}
}
void DirectShowEventLoop::processEvents()
{
QMutexLocker locker(&m_mutex);
::ResetEvent(m_eventHandle);
while(m_postsHead) {
DirectShowPostedEvent *post = m_postsHead;
m_postsHead = m_postsHead->next;
if (!m_postsHead)
m_postsTail = 0;
locker.unlock();
QCoreApplication::sendEvent(post->receiver, post->event);
delete post;
locker.relock();
}
}

View File

@@ -0,0 +1,78 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DIRECTSHOWEVENTLOOP_H
#define DIRECTSHOWEVENTLOOP_H
#include <QtCore/qmutex.h>
#include <QtCore/qobject.h>
#include <QtCore/qwaitcondition.h>
#include <windows.h>
class DirectShowPostedEvent;
class DirectShowEventLoop : public QObject
{
Q_OBJECT
public:
DirectShowEventLoop(QObject *parent = 0);
~DirectShowEventLoop();
void wait(QMutex *mutex);
void wake();
void postEvent(QObject *object, QEvent *event);
protected:
void customEvent(QEvent *event);
private:
void processEvents();
DirectShowPostedEvent *m_postsHead;
DirectShowPostedEvent *m_postsTail;
HANDLE m_eventHandle;
HANDLE m_waitHandle;
QMutex m_mutex;
};
#endif

View File

@@ -0,0 +1,139 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DIRECTSHOWGLOBAL_H
#define DIRECTSHOWGLOBAL_H
#include <QtCore/qglobal.h>
#include <dshow.h>
template <typename T> T *com_cast(IUnknown *unknown, const IID &iid)
{
T *iface = 0;
return unknown && unknown->QueryInterface(iid, reinterpret_cast<void **>(&iface)) == S_OK
? iface
: 0;
}
template <typename T> T *com_new(const IID &clsid, const IID &iid)
{
T *object = 0;
return CoCreateInstance(
clsid,
NULL,
CLSCTX_INPROC_SERVER,
iid,
reinterpret_cast<void **>(&object)) == S_OK
? object
: 0;
}
#ifndef __IFilterGraph2_INTERFACE_DEFINED__
#define __IFilterGraph2_INTERFACE_DEFINED__
#define INTERFACE IFilterGraph2
DECLARE_INTERFACE_(IFilterGraph2 ,IGraphBuilder)
{
STDMETHOD(AddSourceFilterForMoniker)(THIS_ IMoniker *, IBindCtx *, LPCWSTR,IBaseFilter **) PURE;
STDMETHOD(ReconnectEx)(THIS_ IPin *, const AM_MEDIA_TYPE *) PURE;
STDMETHOD(RenderEx)(IPin *, DWORD, DWORD *) PURE;
};
#undef INTERFACE
#endif
#ifndef __IAMFilterMiscFlags_INTERFACE_DEFINED__
#define __IAMFilterMiscFlags_INTERFACE_DEFINED__
#define INTERFACE IAMFilterMiscFlags
DECLARE_INTERFACE_(IAMFilterMiscFlags ,IUnknown)
{
STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
STDMETHOD_(ULONG,GetMiscFlags)(THIS) PURE;
};
#undef INTERFACE
#endif
#ifndef __IFileSourceFilter_INTERFACE_DEFINED__
#define __IFileSourceFilter_INTERFACE_DEFINED__
#define INTERFACE IFileSourceFilter
DECLARE_INTERFACE_(IFileSourceFilter ,IUnknown)
{
STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
STDMETHOD(Load)(THIS_ LPCOLESTR, const AM_MEDIA_TYPE *) PURE;
STDMETHOD(GetCurFile)(THIS_ LPOLESTR *ppszFileName, AM_MEDIA_TYPE *) PURE;
};
#undef INTERFACE
#endif
#ifndef __IAMOpenProgress_INTERFACE_DEFINED__
#define __IAMOpenProgress_INTERFACE_DEFINED__
#define INTERFACE IAMOpenProgress
DECLARE_INTERFACE_(IAMOpenProgress ,IUnknown)
{
STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
STDMETHOD(QueryProgress)(THIS_ LONGLONG *, LONGLONG *) PURE;
STDMETHOD(AbortOperation)(THIS) PURE;
};
#undef INTERFACE
#endif
#ifndef __IFilterChain_INTERFACE_DEFINED__
#define __IFilterChain_INTERFACE_DEFINED__
#define INTERFACE IFilterChain
DECLARE_INTERFACE_(IFilterChain ,IUnknown)
{
STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
STDMETHOD(StartChain)(IBaseFilter *, IBaseFilter *) PURE;
STDMETHOD(PauseChain)(IBaseFilter *, IBaseFilter *) PURE;
STDMETHOD(StopChain)(IBaseFilter *, IBaseFilter *) PURE;
STDMETHOD(RemoveChain)(IBaseFilter *, IBaseFilter *) PURE;
};
#undef INTERFACE
#endif
#endif

View File

@@ -0,0 +1,496 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "directshowioreader.h"
#include "directshoweventloop.h"
#include "directshowglobal.h"
#include "directshowiosource.h"
#include <QtCore/qcoreapplication.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qiodevice.h>
#include <QtCore/qthread.h>
class DirectShowSampleRequest
{
public:
DirectShowSampleRequest(
IMediaSample *sample, DWORD_PTR userData, LONGLONG position, LONG length, BYTE *buffer)
: next(0)
, sample(sample)
, userData(userData)
, position(position)
, length(length)
, buffer(buffer)
, result(S_FALSE)
{
}
DirectShowSampleRequest *remove() { DirectShowSampleRequest *n = next; delete this; return n; }
DirectShowSampleRequest *next;
IMediaSample *sample;
DWORD_PTR userData;
LONGLONG position;
LONG length;
BYTE *buffer;
HRESULT result;
};
DirectShowIOReader::DirectShowIOReader(
QIODevice *device, DirectShowIOSource *source, DirectShowEventLoop *loop)
: m_source(source)
, m_device(device)
, m_loop(loop)
, m_pendingHead(0)
, m_pendingTail(0)
, m_readyHead(0)
, m_readyTail(0)
, m_synchronousPosition(0)
, m_synchronousLength(0)
, m_synchronousBytesRead(0)
, m_synchronousBuffer(0)
, m_synchronousResult(S_OK)
, m_totalLength(0)
, m_availableLength(0)
, m_flushing(false)
{
moveToThread(device->thread());
connect(device, SIGNAL(readyRead()), this, SLOT(readyRead()));
}
DirectShowIOReader::~DirectShowIOReader()
{
flushRequests();
}
HRESULT DirectShowIOReader::QueryInterface(REFIID riid, void **ppvObject)
{
return m_source->QueryInterface(riid, ppvObject);
}
ULONG DirectShowIOReader::AddRef()
{
return m_source->AddRef();
}
ULONG DirectShowIOReader::Release()
{
return m_source->Release();
}
// IAsyncReader
HRESULT DirectShowIOReader::RequestAllocator(
IMemAllocator *pPreferred, ALLOCATOR_PROPERTIES *pProps, IMemAllocator **ppActual)
{
if (!ppActual || !pProps) {
return E_POINTER;
} else {
ALLOCATOR_PROPERTIES actualProperties;
if (pProps->cbAlign == 0)
pProps->cbAlign = 1;
if (pPreferred && pPreferred->SetProperties(pProps, &actualProperties) == S_OK) {
pPreferred->AddRef();
*ppActual = pPreferred;
m_source->setAllocator(*ppActual);
return S_OK;
} else {
*ppActual = com_new<IMemAllocator>(CLSID_MemoryAllocator, IID_IMemAllocator);
if (*ppActual) {
if ((*ppActual)->SetProperties(pProps, &actualProperties) != S_OK) {
(*ppActual)->Release();
} else {
m_source->setAllocator(*ppActual);
return S_OK;
}
}
}
ppActual = 0;
return E_FAIL;
}
}
HRESULT DirectShowIOReader::Request(IMediaSample *pSample, DWORD_PTR dwUser)
{
QMutexLocker locker(&m_mutex);
if (!pSample) {
return E_POINTER;
} else if (m_flushing) {
return VFW_E_WRONG_STATE;
} else {
REFERENCE_TIME startTime = 0;
REFERENCE_TIME endTime = 0;
BYTE *buffer;
if (pSample->GetTime(&startTime, &endTime) != S_OK
|| pSample->GetPointer(&buffer) != S_OK) {
return VFW_E_SAMPLE_TIME_NOT_SET;
} else {
LONGLONG position = startTime / 10000000;
LONG length = (endTime - startTime) / 10000000;
DirectShowSampleRequest *request = new DirectShowSampleRequest(
pSample, dwUser, position, length, buffer);
if (m_pendingTail) {
m_pendingTail->next = request;
} else {
m_pendingHead = request;
m_loop->postEvent(this, new QEvent(QEvent::User));
}
m_pendingTail = request;
return S_OK;
}
}
}
HRESULT DirectShowIOReader::WaitForNext(
DWORD dwTimeout, IMediaSample **ppSample, DWORD_PTR *pdwUser)
{
if (!ppSample || !pdwUser)
return E_POINTER;
QMutexLocker locker(&m_mutex);
do {
if (m_readyHead) {
DirectShowSampleRequest *request = m_readyHead;
*ppSample = request->sample;
*pdwUser = request->userData;
HRESULT hr = request->result;
m_readyHead = request->next;
if (!m_readyHead)
m_readyTail = 0;
delete request;
return hr;
} else if (m_flushing) {
*ppSample = 0;
*pdwUser = 0;
return VFW_E_WRONG_STATE;
}
} while (m_wait.wait(&m_mutex, dwTimeout));
*ppSample = 0;
*pdwUser = 0;
return VFW_E_TIMEOUT;
}
HRESULT DirectShowIOReader::SyncReadAligned(IMediaSample *pSample)
{
if (!pSample) {
return E_POINTER;
} else {
REFERENCE_TIME startTime = 0;
REFERENCE_TIME endTime = 0;
BYTE *buffer;
if (pSample->GetTime(&startTime, &endTime) != S_OK
|| pSample->GetPointer(&buffer) != S_OK) {
return VFW_E_SAMPLE_TIME_NOT_SET;
} else {
LONGLONG position = startTime / 10000000;
LONG length = (endTime - startTime) / 10000000;
QMutexLocker locker(&m_mutex);
if (thread() == QThread::currentThread()) {
qint64 bytesRead = 0;
HRESULT hr = blockingRead(position, length, buffer, &bytesRead);
if (SUCCEEDED(hr))
pSample->SetActualDataLength(bytesRead);
return hr;
} else {
m_synchronousPosition = position;
m_synchronousLength = length;
m_synchronousBuffer = buffer;
m_loop->postEvent(this, new QEvent(QEvent::User));
m_wait.wait(&m_mutex);
m_synchronousBuffer = 0;
if (SUCCEEDED(m_synchronousResult))
pSample->SetActualDataLength(m_synchronousBytesRead);
return m_synchronousResult;
}
}
}
}
HRESULT DirectShowIOReader::SyncRead(LONGLONG llPosition, LONG lLength, BYTE *pBuffer)
{
if (!pBuffer) {
return E_POINTER;
} else {
if (thread() == QThread::currentThread()) {
qint64 bytesRead;
return blockingRead(llPosition, lLength, pBuffer, &bytesRead);
} else {
QMutexLocker locker(&m_mutex);
m_synchronousPosition = llPosition;
m_synchronousLength = lLength;
m_synchronousBuffer = pBuffer;
m_loop->postEvent(this, new QEvent(QEvent::User));
m_wait.wait(&m_mutex);
m_synchronousBuffer = 0;
return m_synchronousResult;
}
}
}
HRESULT DirectShowIOReader::Length(LONGLONG *pTotal, LONGLONG *pAvailable)
{
if (!pTotal || !pAvailable) {
return E_POINTER;
} else {
QMutexLocker locker(&m_mutex);
*pTotal = m_totalLength;
*pAvailable = m_availableLength;
return S_OK;
}
}
HRESULT DirectShowIOReader::BeginFlush()
{
QMutexLocker locker(&m_mutex);
if (m_flushing)
return S_FALSE;
m_flushing = true;
flushRequests();
m_wait.wakeAll();
return S_OK;
}
HRESULT DirectShowIOReader::EndFlush()
{
QMutexLocker locker(&m_mutex);
if (!m_flushing)
return S_FALSE;
m_flushing = false;
return S_OK;
}
void DirectShowIOReader::customEvent(QEvent *event)
{
if (event->type() == QEvent::User) {
readyRead();
} else {
QObject::customEvent(event);
}
}
void DirectShowIOReader::readyRead()
{
QMutexLocker locker(&m_mutex);
m_availableLength = m_device->bytesAvailable() + m_device->pos();
m_totalLength = m_device->size();
if (m_synchronousBuffer) {
if (nonBlockingRead(
m_synchronousPosition,
m_synchronousLength,
m_synchronousBuffer,
&m_synchronousBytesRead,
&m_synchronousResult)) {
m_wait.wakeAll();
}
} else {
qint64 bytesRead = 0;
while (m_pendingHead && nonBlockingRead(
m_pendingHead->position,
m_pendingHead->length,
m_pendingHead->buffer,
&bytesRead,
&m_pendingHead->result)) {
m_pendingHead->sample->SetActualDataLength(bytesRead);
if (m_readyTail)
m_readyTail->next = m_pendingHead;
m_readyTail = m_pendingHead;
m_pendingHead = m_pendingHead->next;
m_readyTail->next = 0;
if (!m_pendingHead)
m_pendingTail = 0;
if (!m_readyHead)
m_readyHead = m_readyTail;
m_wait.wakeAll();
}
}
}
HRESULT DirectShowIOReader::blockingRead(
LONGLONG position, LONG length, BYTE *buffer, qint64 *bytesRead)
{
*bytesRead = 0;
if (qint64(position) > m_device->size())
return S_FALSE;
const qint64 maxSize = qMin<qint64>(m_device->size(), position + length);
while (m_device->bytesAvailable() + m_device->pos() < maxSize) {
if (!m_device->waitForReadyRead(-1))
return S_FALSE;
}
if (m_device->pos() != position && !m_device->seek(position))
return S_FALSE;
const qint64 maxBytes = qMin<qint64>(length, m_device->bytesAvailable());
*bytesRead = m_device->read(reinterpret_cast<char *>(buffer), maxBytes);
if (*bytesRead != length) {
qMemSet(buffer + *bytesRead, 0, length - *bytesRead);
return S_FALSE;
} else {
return S_OK;
}
}
bool DirectShowIOReader::nonBlockingRead(
LONGLONG position, LONG length, BYTE *buffer, qint64 *bytesRead, HRESULT *result)
{
const qint64 maxSize = qMin<qint64>(m_device->size(), position + length);
if (position > m_device->size()) {
*bytesRead = 0;
*result = S_FALSE;
return true;
} else if (m_device->bytesAvailable() + m_device->pos() >= maxSize) {
if (m_device->pos() != position && !m_device->seek(position)) {
*bytesRead = 0;
*result = S_FALSE;
return true;
} else {
const qint64 maxBytes = qMin<qint64>(length, m_device->bytesAvailable());
*bytesRead = m_device->read(reinterpret_cast<char *>(buffer), maxBytes);
if (*bytesRead != length) {
qMemSet(buffer + *bytesRead, 0, length - *bytesRead);
*result = S_FALSE;
} else {
*result = S_OK;
}
return true;
}
} else {
return false;
}
}
void DirectShowIOReader::flushRequests()
{
while (m_pendingHead) {
m_pendingHead->result = VFW_E_WRONG_STATE;
if (m_readyTail)
m_readyTail->next = m_pendingHead;
m_readyTail = m_pendingHead;
m_pendingHead = m_pendingHead->next;
m_readyTail->next = 0;
if (!m_pendingHead)
m_pendingTail = 0;
if (!m_readyHead)
m_readyHead = m_readyTail;
}
}

View File

@@ -0,0 +1,120 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DIRECTSHOWIOREADER_H
#define DIRECTSHOWIOREADER_H
#include <QtCore/qmutex.h>
#include <QtCore/qobject.h>
#include <QtCore/qwaitcondition.h>
#include <dshow.h>
QT_BEGIN_NAMESPACE
class QIODevice;
QT_END_NAMESPACE
class DirectShowEventLoop;
class DirectShowIOSource;
class DirectShowSampleRequest;
class DirectShowIOReader : public QObject, public IAsyncReader
{
Q_OBJECT
public:
DirectShowIOReader(QIODevice *device, DirectShowIOSource *source, DirectShowEventLoop *loop);
~DirectShowIOReader();
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
// IAsyncReader
HRESULT STDMETHODCALLTYPE RequestAllocator(
IMemAllocator *pPreferred, ALLOCATOR_PROPERTIES *pProps, IMemAllocator **ppActual);
HRESULT STDMETHODCALLTYPE Request(IMediaSample *pSample, DWORD_PTR dwUser);
HRESULT STDMETHODCALLTYPE WaitForNext(
DWORD dwTimeout, IMediaSample **ppSample, DWORD_PTR *pdwUser);
HRESULT STDMETHODCALLTYPE SyncReadAligned(IMediaSample *pSample);
HRESULT STDMETHODCALLTYPE SyncRead(LONGLONG llPosition, LONG lLength, BYTE *pBuffer);
HRESULT STDMETHODCALLTYPE Length(LONGLONG *pTotal, LONGLONG *pAvailable);
HRESULT STDMETHODCALLTYPE BeginFlush();
HRESULT STDMETHODCALLTYPE EndFlush();
protected:
void customEvent(QEvent *event);
private Q_SLOTS:
void readyRead();
private:
HRESULT blockingRead(LONGLONG position, LONG length, BYTE *buffer, qint64 *bytesRead);
bool nonBlockingRead(
LONGLONG position, LONG length, BYTE *buffer, qint64 *bytesRead, HRESULT *result);
void flushRequests();
DirectShowIOSource *m_source;
QIODevice *m_device;
DirectShowEventLoop *m_loop;
DirectShowSampleRequest *m_pendingHead;
DirectShowSampleRequest *m_pendingTail;
DirectShowSampleRequest *m_readyHead;
DirectShowSampleRequest *m_readyTail;
LONGLONG m_synchronousPosition;
LONG m_synchronousLength;
qint64 m_synchronousBytesRead;
BYTE *m_synchronousBuffer;
HRESULT m_synchronousResult;
LONGLONG m_totalLength;
LONGLONG m_availableLength;
bool m_flushing;
QMutex m_mutex;
QWaitCondition m_wait;
};
#endif

View File

@@ -0,0 +1,639 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "directshowiosource.h"
#include "directshowglobal.h"
#include "directshowmediatype.h"
#include "directshowpinenum.h"
#include <QtCore/qcoreapplication.h>
#include <QtCore/qurl.h>
static const GUID directshow_subtypes[] =
{
MEDIASUBTYPE_Avi,
MEDIASUBTYPE_WAVE,
MEDIASUBTYPE_NULL
};
DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop)
: m_ref(1)
, m_state(State_Stopped)
, m_reader(0)
, m_loop(loop)
, m_graph(0)
, m_clock(0)
, m_allocator(0)
, m_peerPin(0)
, m_pinId(QLatin1String("Data"))
{
QVector<AM_MEDIA_TYPE> mediaTypes;
AM_MEDIA_TYPE type =
{
MEDIATYPE_Stream, // majortype
MEDIASUBTYPE_NULL, // subtype
TRUE, // bFixedSizeSamples
FALSE, // bTemporalCompression
1, // lSampleSize
GUID_NULL, // formattype
0, // pUnk
0, // cbFormat
0, // pbFormat
};
static const int count = sizeof(directshow_subtypes) / sizeof(GUID);
for (int i = 0; i < count; ++i) {
type.subtype = directshow_subtypes[i];
mediaTypes.append(type);
}
setMediaTypes(mediaTypes);
}
DirectShowIOSource::~DirectShowIOSource()
{
Q_ASSERT(m_ref == 0);
delete m_reader;
}
void DirectShowIOSource::setDevice(QIODevice *device)
{
Q_ASSERT(!m_reader);
m_reader = new DirectShowIOReader(device, this, m_loop);
}
void DirectShowIOSource::setAllocator(IMemAllocator *allocator)
{
if (m_allocator)
m_allocator->Release();
m_allocator = allocator;
if (m_allocator)
m_allocator->AddRef();
}
// IUnknown
HRESULT DirectShowIOSource::QueryInterface(REFIID riid, void **ppvObject)
{
// 2dd74950-a890-11d1-abe8-00a0c905f375
static const GUID iid_IAmFilterMiscFlags = {
0x2dd74950, 0xa890, 0x11d1, {0xab, 0xe8, 0x00, 0xa0, 0xc9, 0x05, 0xf3, 0x75}};
if (!ppvObject) {
return E_POINTER;
} else if (riid == IID_IUnknown
|| riid == IID_IPersist
|| riid == IID_IMediaFilter
|| riid == IID_IBaseFilter) {
*ppvObject = static_cast<IBaseFilter *>(this);
} else if (riid == iid_IAmFilterMiscFlags) {
*ppvObject = static_cast<IAMFilterMiscFlags *>(this);
} else if (riid == IID_IPin) {
*ppvObject = static_cast<IPin *>(this);
} else if (riid == IID_IAsyncReader) {
*ppvObject = static_cast<IAsyncReader *>(m_reader);
} else {
*ppvObject = 0;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
ULONG DirectShowIOSource::AddRef()
{
return InterlockedIncrement(&m_ref);
}
ULONG DirectShowIOSource::Release()
{
ULONG ref = InterlockedDecrement(&m_ref);
if (ref == 0) {
delete this;
}
return ref;
}
// IPersist
HRESULT DirectShowIOSource::GetClassID(CLSID *pClassID)
{
*pClassID = CLSID_NULL;
return S_OK;
}
// IMediaFilter
HRESULT DirectShowIOSource::Run(REFERENCE_TIME tStart)
{
QMutexLocker locker(&m_mutex);
m_state = State_Running;
return S_OK;
}
HRESULT DirectShowIOSource::Pause()
{
QMutexLocker locker(&m_mutex);
m_state = State_Paused;
return S_OK;
}
HRESULT DirectShowIOSource::Stop()
{
QMutexLocker locker(&m_mutex);
m_state = State_Stopped;
return S_OK;
}
HRESULT DirectShowIOSource::GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
{
Q_UNUSED(dwMilliSecsTimeout);
if (!pState) {
return E_POINTER;
} else {
QMutexLocker locker(&m_mutex);
*pState = m_state;
return S_OK;
}
}
HRESULT DirectShowIOSource::SetSyncSource(IReferenceClock *pClock)
{
QMutexLocker locker(&m_mutex);
if (m_clock)
m_clock->Release();
m_clock = pClock;
if (m_clock)
m_clock->AddRef();
return S_OK;
}
HRESULT DirectShowIOSource::GetSyncSource(IReferenceClock **ppClock)
{
if (!ppClock) {
return E_POINTER;
} else {
if (!m_clock) {
*ppClock = 0;
return S_FALSE;
} else {
m_clock->AddRef();
*ppClock = m_clock;
return S_OK;
}
}
}
// IBaseFilter
HRESULT DirectShowIOSource::EnumPins(IEnumPins **ppEnum)
{
if (!ppEnum) {
return E_POINTER;
} else {
*ppEnum = new DirectShowPinEnum(QList<IPin *>() << this);
return S_OK;
}
}
HRESULT DirectShowIOSource::FindPin(LPCWSTR Id, IPin **ppPin)
{
if (!ppPin || !Id) {
return E_POINTER;
} else {
QMutexLocker locker(&m_mutex);
if (QString::fromWCharArray(Id) == m_pinId) {
AddRef();
*ppPin = this;
return S_OK;
} else {
*ppPin = 0;
return VFW_E_NOT_FOUND;
}
}
}
HRESULT DirectShowIOSource::JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName)
{
QMutexLocker locker(&m_mutex);
m_graph = pGraph;
m_filterName = QString::fromWCharArray(pName);
return S_OK;
}
HRESULT DirectShowIOSource::QueryFilterInfo(FILTER_INFO *pInfo)
{
if (!pInfo) {
return E_POINTER;
} else {
QString name = m_filterName;
if (name.length() >= MAX_FILTER_NAME)
name.truncate(MAX_FILTER_NAME - 1);
int length = name.toWCharArray(pInfo->achName);
pInfo->achName[length] = '\0';
if (m_graph)
m_graph->AddRef();
pInfo->pGraph = m_graph;
return S_OK;
}
}
HRESULT DirectShowIOSource::QueryVendorInfo(LPWSTR *pVendorInfo)
{
Q_UNUSED(pVendorInfo);
return E_NOTIMPL;
}
// IAMFilterMiscFlags
ULONG DirectShowIOSource::GetMiscFlags()
{
return AM_FILTER_MISC_FLAGS_IS_SOURCE;
}
// IPin
HRESULT DirectShowIOSource::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
{
QMutexLocker locker(&m_mutex);
if (!pReceivePin) {
return E_POINTER;
} else if (m_state != State_Stopped) {
return VFW_E_NOT_STOPPED;
} else if (m_peerPin) {
return VFW_E_ALREADY_CONNECTED;
} else {
HRESULT hr = VFW_E_TYPE_NOT_ACCEPTED;
m_peerPin = pReceivePin;
m_peerPin->AddRef();
if (!pmt) {
IEnumMediaTypes *mediaTypes = 0;
if (pReceivePin->EnumMediaTypes(&mediaTypes) == S_OK) {
for (AM_MEDIA_TYPE *type = 0;
mediaTypes->Next(1, &type, 0) == S_OK;
DirectShowMediaType::deleteType(type)) {
switch (tryConnect(pReceivePin, type)) {
case S_OK:
DirectShowMediaType::freeData(type);
mediaTypes->Release();
return S_OK;
case VFW_E_NO_TRANSPORT:
hr = VFW_E_NO_TRANSPORT;
break;
default:
break;
}
}
mediaTypes->Release();
}
AM_MEDIA_TYPE type =
{
MEDIATYPE_Stream, // majortype
MEDIASUBTYPE_NULL, // subtype
TRUE, // bFixedSizeSamples
FALSE, // bTemporalCompression
1, // lSampleSize
GUID_NULL, // formattype
0, // pUnk
0, // cbFormat
0, // pbFormat
};
static const int count = sizeof(directshow_subtypes) / sizeof(GUID);
for (int i = 0; i < count; ++i) {
type.subtype = directshow_subtypes[i];
switch (tryConnect(pReceivePin, &type)) {
case S_OK:
return S_OK;
case VFW_E_NO_TRANSPORT:
hr = VFW_E_NO_TRANSPORT;
break;
default:
break;
}
}
} else if (pmt->majortype == MEDIATYPE_Stream && (hr = tryConnect(pReceivePin, pmt))) {
return S_OK;
}
m_peerPin->Release();
m_peerPin = 0;
m_mediaType.clear();
return hr;
}
}
HRESULT DirectShowIOSource::tryConnect(IPin *pin, const AM_MEDIA_TYPE *type)
{
m_mediaType = *type;
HRESULT hr = pin->ReceiveConnection(this, type);
if (!SUCCEEDED(hr)) {
if (m_allocator) {
m_allocator->Release();
m_allocator = 0;
}
} else if (!m_allocator) {
hr = VFW_E_NO_TRANSPORT;
if (IMemInputPin *memPin = com_cast<IMemInputPin>(pin, IID_IMemInputPin)) {
if ((m_allocator = com_new<IMemAllocator>(CLSID_MemoryAllocator, IID_IMemAllocator))) {
ALLOCATOR_PROPERTIES properties;
if (memPin->GetAllocatorRequirements(&properties) == S_OK
|| m_allocator->GetProperties(&properties) == S_OK) {
if (properties.cbAlign == 0)
properties.cbAlign = 1;
ALLOCATOR_PROPERTIES actualProperties;
if (SUCCEEDED(hr = m_allocator->SetProperties(&properties, &actualProperties)))
hr = memPin->NotifyAllocator(m_allocator, TRUE);
}
if (!SUCCEEDED(hr)) {
m_allocator->Release();
m_allocator = 0;
}
}
memPin->Release();
}
if (!SUCCEEDED(hr))
pin->Disconnect();
}
return hr;
}
HRESULT DirectShowIOSource::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
{
Q_UNUSED(pConnector);
Q_UNUSED(pmt);
// Output pin.
return E_NOTIMPL;
}
HRESULT DirectShowIOSource::Disconnect()
{
if (!m_peerPin) {
return S_FALSE;
} else if (m_state != State_Stopped) {
return VFW_E_NOT_STOPPED;
} else {
HRESULT hr = m_peerPin->Disconnect();
if (!SUCCEEDED(hr))
return hr;
if (m_allocator) {
m_allocator->Release();
m_allocator = 0;
}
m_peerPin->Release();
m_peerPin = 0;
m_mediaType.clear();
return S_OK;
}
}
HRESULT DirectShowIOSource::ConnectedTo(IPin **ppPin)
{
if (!ppPin) {
return E_POINTER;
} else {
QMutexLocker locker(&m_mutex);
if (!m_peerPin) {
*ppPin = 0;
return VFW_E_NOT_CONNECTED;
} else {
m_peerPin->AddRef();
*ppPin = m_peerPin;
return S_OK;
}
}
}
HRESULT DirectShowIOSource::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
{
if (!pmt) {
return E_POINTER;
} else {
QMutexLocker locker(&m_mutex);
if (!m_peerPin) {
pmt = 0;
return VFW_E_NOT_CONNECTED;
} else {
DirectShowMediaType::copy(pmt, m_mediaType);
return S_OK;
}
}
}
HRESULT DirectShowIOSource::QueryPinInfo(PIN_INFO *pInfo)
{
if (!pInfo) {
return E_POINTER;
} else {
AddRef();
pInfo->pFilter = this;
pInfo->dir = PINDIR_OUTPUT;
const int bytes = qMin(MAX_FILTER_NAME, (m_pinId.length() + 1) * 2);
qMemCopy(pInfo->achName, m_pinId.utf16(), bytes);
return S_OK;
}
}
HRESULT DirectShowIOSource::QueryId(LPWSTR *Id)
{
if (!Id) {
return E_POINTER;
} else {
const int bytes = (m_pinId.length() + 1) * 2;
*Id = static_cast<LPWSTR>(::CoTaskMemAlloc(bytes));
qMemCopy(*Id, m_pinId.utf16(), bytes);
return S_OK;
}
}
HRESULT DirectShowIOSource::QueryAccept(const AM_MEDIA_TYPE *pmt)
{
if (!pmt) {
return E_POINTER;
} else if (pmt->majortype == MEDIATYPE_Stream) {
return S_OK;
} else {
return S_FALSE;
}
}
HRESULT DirectShowIOSource::EnumMediaTypes(IEnumMediaTypes **ppEnum)
{
if (!ppEnum) {
return E_POINTER;
} else {
*ppEnum = createMediaTypeEnum();
return S_OK;
}
}
HRESULT DirectShowIOSource::QueryInternalConnections(IPin **apPin, ULONG *nPin)
{
Q_UNUSED(apPin);
Q_UNUSED(nPin);
return E_NOTIMPL;
}
HRESULT DirectShowIOSource::EndOfStream()
{
return S_OK;
}
HRESULT DirectShowIOSource::BeginFlush()
{
return m_reader->BeginFlush();
}
HRESULT DirectShowIOSource::EndFlush()
{
return m_reader->EndFlush();
}
HRESULT DirectShowIOSource::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
{
Q_UNUSED(tStart);
Q_UNUSED(tStop);
Q_UNUSED(dRate);
return S_OK;
}
HRESULT DirectShowIOSource::QueryDirection(PIN_DIRECTION *pPinDir)
{
if (!pPinDir) {
return E_POINTER;
} else {
*pPinDir = PINDIR_OUTPUT;
return S_OK;
}
}
DirectShowRcSource::DirectShowRcSource(DirectShowEventLoop *loop)
: DirectShowIOSource(loop)
{
}
bool DirectShowRcSource::open(const QUrl &url)
{
m_file.moveToThread(QCoreApplication::instance()->thread());
m_file.setFileName(QLatin1Char(':') + url.path());
qDebug("qrc file %s", qPrintable(m_file.fileName()));
if (m_file.open(QIODevice::ReadOnly)) {
qDebug("Size %d", m_file.size());
qDebug("Sequential %d", int(m_file.isSequential()));
setDevice(&m_file);
return true;
} else {
return false;
}
}

View File

@@ -0,0 +1,149 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DIRECTSHOWIOSOURCE_H
#define DIRECTSHOWIOSOURCE_H
#include "directshowglobal.h"
#include "directshowioreader.h"
#include "directshowmediatype.h"
#include "directshowmediatypelist.h"
#include <QtCore/qfile.h>
class DirectShowIOSource
: public DirectShowMediaTypeList
, public IBaseFilter
, public IAMFilterMiscFlags
, public IPin
{
public:
DirectShowIOSource(DirectShowEventLoop *loop);
~DirectShowIOSource();
void setDevice(QIODevice *device);
void setAllocator(IMemAllocator *allocator);
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
// IPersist
HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
// IMediaFilter
HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart);
HRESULT STDMETHODCALLTYPE Pause();
HRESULT STDMETHODCALLTYPE Stop();
HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState);
HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock);
HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **ppClock);
// IBaseFilter
HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **ppEnum);
HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin **ppPin);
HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName);
HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *pInfo);
HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *pVendorInfo);
// IAMFilterMiscFlags
ULONG STDMETHODCALLTYPE GetMiscFlags();
// IPin
HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE Disconnect();
HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **ppPin);
HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo);
HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id);
HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum);
HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin);
HRESULT STDMETHODCALLTYPE EndOfStream();
HRESULT STDMETHODCALLTYPE BeginFlush();
HRESULT STDMETHODCALLTYPE EndFlush();
HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir);
private:
HRESULT tryConnect(IPin *pin, const AM_MEDIA_TYPE *type);
volatile LONG m_ref;
FILTER_STATE m_state;
DirectShowIOReader *m_reader;
DirectShowEventLoop *m_loop;
IFilterGraph *m_graph;
IReferenceClock *m_clock;
IMemAllocator *m_allocator;
IPin *m_peerPin;
DirectShowMediaType m_mediaType;
QString m_filterName;
const QString m_pinId;
QMutex m_mutex;
};
class DirectShowRcSource : public DirectShowIOSource
{
public:
DirectShowRcSource(DirectShowEventLoop *loop);
bool open(const QUrl &url);
private:
QFile m_file;
};
#endif

View File

@@ -0,0 +1,184 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "directshowmediatype.h"
namespace
{
struct TypeLookup
{
QVideoFrame::PixelFormat pixelFormat;
GUID mediaType;
};
static const TypeLookup qt_typeLookup[] =
{
{ QVideoFrame::Format_RGB32, /*MEDIASUBTYPE_RGB32*/ {0xe436eb7e, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} },
{ QVideoFrame::Format_BGR24, /*MEDIASUBTYPE_RGB24*/ {0xe436eb7d, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} },
{ QVideoFrame::Format_RGB565, /*MEDIASUBTYPE_RGB565*/ {0xe436eb7b, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} },
{ QVideoFrame::Format_RGB555, /*MEDIASUBTYPE_RGB555*/ {0xe436eb7c, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} },
{ QVideoFrame::Format_AYUV444, /*MEDIASUBTYPE_AYUV*/ {0x56555941, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
{ QVideoFrame::Format_YUYV, /*MEDIASUBTYPE_YUY2*/ {0x32595559, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
{ QVideoFrame::Format_UYVY, /*MEDIASUBTYPE_UYVY*/ {0x59565955, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
{ QVideoFrame::Format_IMC1, /*MEDIASUBTYPE_IMC1*/ {0x31434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
{ QVideoFrame::Format_IMC2, /*MEDIASUBTYPE_IMC2*/ {0x32434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
{ QVideoFrame::Format_IMC3, /*MEDIASUBTYPE_IMC3*/ {0x33434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
{ QVideoFrame::Format_IMC4, /*MEDIASUBTYPE_IMC4*/ {0x34434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
{ QVideoFrame::Format_YV12, /*MEDIASUBTYPE_YV12*/ {0x32315659, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
{ QVideoFrame::Format_NV12, /*MEDIASUBTYPE_NV12*/ {0x3231564E, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
{ QVideoFrame::Format_YUV420P, /*MEDIASUBTYPE_IYUV*/ {0x56555949, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} }
};
}
void DirectShowMediaType::copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE &source)
{
*target = source;
if (source.cbFormat > 0) {
target->pbFormat = reinterpret_cast<PBYTE>(CoTaskMemAlloc(source.cbFormat));
memcpy(target->pbFormat, source.pbFormat, source.cbFormat);
}
if (target->pUnk)
target->pUnk->AddRef();
}
void DirectShowMediaType::deleteType(AM_MEDIA_TYPE *type)
{
freeData(type);
CoTaskMemFree(type);
}
void DirectShowMediaType::freeData(AM_MEDIA_TYPE *type)
{
if (type->cbFormat > 0)
CoTaskMemFree(type->pbFormat);
if (type->pUnk)
type->pUnk->Release();
}
GUID DirectShowMediaType::convertPixelFormat(QVideoFrame::PixelFormat format)
{
// MEDIASUBTYPE_None;
static const GUID none = {
0xe436eb8e, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70} };
const int count = sizeof(qt_typeLookup) / sizeof(TypeLookup);
for (int i = 0; i < count; ++i)
if (qt_typeLookup[i].pixelFormat == format)
return qt_typeLookup[i].mediaType;
return none;
}
QVideoSurfaceFormat DirectShowMediaType::formatFromType(const AM_MEDIA_TYPE &type)
{
const int count = sizeof(qt_typeLookup) / sizeof(TypeLookup);
for (int i = 0; i < count; ++i) {
if (IsEqualGUID(qt_typeLookup[i].mediaType, type.subtype) && type.cbFormat > 0) {
if (IsEqualGUID(type.formattype, FORMAT_VideoInfo)) {
VIDEOINFOHEADER *header = reinterpret_cast<VIDEOINFOHEADER *>(type.pbFormat);
QVideoSurfaceFormat format(
QSize(header->bmiHeader.biWidth, qAbs(header->bmiHeader.biHeight)),
qt_typeLookup[i].pixelFormat);
if (header->AvgTimePerFrame > 0)
format.setFrameRate(10000 /header->AvgTimePerFrame);
format.setScanLineDirection(header->bmiHeader.biHeight < 0
? QVideoSurfaceFormat::TopToBottom
: QVideoSurfaceFormat::BottomToTop);
return format;
} else if (IsEqualGUID(type.formattype, FORMAT_VideoInfo2)) {
VIDEOINFOHEADER2 *header = reinterpret_cast<VIDEOINFOHEADER2 *>(type.pbFormat);
QVideoSurfaceFormat format(
QSize(header->bmiHeader.biWidth, qAbs(header->bmiHeader.biHeight)),
qt_typeLookup[i].pixelFormat);
if (header->AvgTimePerFrame > 0)
format.setFrameRate(10000 / header->AvgTimePerFrame);
format.setScanLineDirection(header->bmiHeader.biHeight < 0
? QVideoSurfaceFormat::TopToBottom
: QVideoSurfaceFormat::BottomToTop);
return format;
}
}
}
return QVideoSurfaceFormat();
}
int DirectShowMediaType::bytesPerLine(const QVideoSurfaceFormat &format)
{
switch (format.pixelFormat()) {
// 32 bpp packed formats.
case QVideoFrame::Format_RGB32:
case QVideoFrame::Format_AYUV444:
return format.frameWidth() * 4;
// 24 bpp packed formats.
case QVideoFrame::Format_RGB24:
return format.frameWidth() * 3 + 3 - format.frameWidth() % 4;
// 16 bpp packed formats.
case QVideoFrame::Format_RGB565:
case QVideoFrame::Format_RGB555:
case QVideoFrame::Format_YUYV:
case QVideoFrame::Format_UYVY:
return format.frameWidth() * 2 + 3 - format.frameWidth() % 4;
// Planar formats.
case QVideoFrame::Format_IMC1:
case QVideoFrame::Format_IMC2:
case QVideoFrame::Format_IMC3:
case QVideoFrame::Format_IMC4:
case QVideoFrame::Format_YV12:
case QVideoFrame::Format_NV12:
case QVideoFrame::Format_YUV420P:
return format.frameWidth() + 3 - format.frameWidth() % 4;
default:
return 0;
}
}

View File

@@ -0,0 +1,74 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DIRECTSHOWMEDIATYPE_H
#define DIRECTSHOWMEDIATYPE_H
#include <qvideosurfaceformat.h>
#include <dshow.h>
#include <dvdmedia.h>
class DirectShowMediaType : public AM_MEDIA_TYPE
{
public:
DirectShowMediaType() { memset(this, 0, sizeof(DirectShowMediaType)); }
DirectShowMediaType(const AM_MEDIA_TYPE &type) { copy(this, type); }
DirectShowMediaType(const DirectShowMediaType &other) { copy(this, other); }
DirectShowMediaType &operator =(const AM_MEDIA_TYPE &type) {
freeData(this); copy(this, type); return *this; }
DirectShowMediaType &operator =(const DirectShowMediaType &other) {
freeData(this); copy(this, other); return *this; }
~DirectShowMediaType() { freeData(this); }
void clear() { freeData(this); memset(this, 0, sizeof(DirectShowMediaType)); }
static void copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE &source);
static void freeData(AM_MEDIA_TYPE *type);
static void deleteType(AM_MEDIA_TYPE *type);
static GUID convertPixelFormat(QVideoFrame::PixelFormat format);
static QVideoSurfaceFormat formatFromType(const AM_MEDIA_TYPE &type);
static int bytesPerLine(const QVideoSurfaceFormat &format);
};
#endif

View File

@@ -0,0 +1,226 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "directshowmediatypelist.h"
#include "directshowmediatype.h"
#include "videosurfacefilter.h"
class DirectShowMediaTypeEnum : public IEnumMediaTypes
{
public:
DirectShowMediaTypeEnum(DirectShowMediaTypeList *list, int token, int index = 0);
~DirectShowMediaTypeEnum();
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
// IEnumMediaTypes
HRESULT STDMETHODCALLTYPE Next(
ULONG cMediaTypes, AM_MEDIA_TYPE **ppMediaTypes, ULONG *pcFetched);
HRESULT STDMETHODCALLTYPE Skip(ULONG cMediaTypes);
HRESULT STDMETHODCALLTYPE Reset();
HRESULT STDMETHODCALLTYPE Clone(IEnumMediaTypes **ppEnum);
private:
LONG m_ref;
DirectShowMediaTypeList *m_list;
int m_mediaTypeToken;
int m_index;
};
DirectShowMediaTypeEnum::DirectShowMediaTypeEnum(
DirectShowMediaTypeList *list, int token, int index)
: m_ref(1)
, m_list(list)
, m_mediaTypeToken(token)
, m_index(index)
{
m_list->AddRef();
}
DirectShowMediaTypeEnum::~DirectShowMediaTypeEnum()
{
m_list->Release();
}
HRESULT DirectShowMediaTypeEnum::QueryInterface(REFIID riid, void **ppvObject)
{
if (!ppvObject) {
return E_POINTER;
} else if (riid == IID_IUnknown
|| riid == IID_IEnumMediaTypes) {
*ppvObject = static_cast<IEnumMediaTypes *>(this);
} else {
*ppvObject = 0;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
ULONG DirectShowMediaTypeEnum::AddRef()
{
return InterlockedIncrement(&m_ref);
}
ULONG DirectShowMediaTypeEnum::Release()
{
ULONG ref = InterlockedDecrement(&m_ref);
if (ref == 0) {
delete this;
}
return ref;
}
HRESULT DirectShowMediaTypeEnum::Next(
ULONG cMediaTypes, AM_MEDIA_TYPE **ppMediaTypes, ULONG *pcFetched)
{
return m_list->nextMediaType(m_mediaTypeToken, &m_index, cMediaTypes, ppMediaTypes, pcFetched);
}
HRESULT DirectShowMediaTypeEnum::Skip(ULONG cMediaTypes)
{
return m_list->skipMediaType(m_mediaTypeToken, &m_index, cMediaTypes);
}
HRESULT DirectShowMediaTypeEnum::Reset()
{
m_mediaTypeToken = m_list->currentMediaTypeToken();
m_index = 0;
return S_OK;
}
HRESULT DirectShowMediaTypeEnum::Clone(IEnumMediaTypes **ppEnum)
{
return m_list->cloneMediaType(m_mediaTypeToken, m_index, ppEnum);
}
DirectShowMediaTypeList::DirectShowMediaTypeList()
: m_mediaTypeToken(0)
{
}
IEnumMediaTypes *DirectShowMediaTypeList::createMediaTypeEnum()
{
return new DirectShowMediaTypeEnum(this, m_mediaTypeToken, 0);
}
void DirectShowMediaTypeList::setMediaTypes(const QVector<AM_MEDIA_TYPE> &types)
{
++m_mediaTypeToken;
m_mediaTypes = types;
}
int DirectShowMediaTypeList::currentMediaTypeToken()
{
return m_mediaTypeToken;
}
HRESULT DirectShowMediaTypeList::nextMediaType(
int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount)
{
if (!types || (count != 1 && !fetchedCount)) {
return E_POINTER;
} else if (m_mediaTypeToken != token) {
return VFW_E_ENUM_OUT_OF_SYNC;
} else {
int boundedCount = qBound<int>(0, count, m_mediaTypes.count() - *index);
for (int i = 0; i < boundedCount; ++i, ++(*index)) {
types[i] = reinterpret_cast<AM_MEDIA_TYPE *>(CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)));
if (types[i]) {
DirectShowMediaType::copy(types[i], m_mediaTypes.at(*index));
} else {
for (--i; i >= 0; --i)
CoTaskMemFree(types[i]);
if (fetchedCount)
*fetchedCount = 0;
return E_OUTOFMEMORY;
}
}
if (fetchedCount)
*fetchedCount = boundedCount;
return boundedCount == count ? S_OK : S_FALSE;
}
}
HRESULT DirectShowMediaTypeList::skipMediaType(int token, int *index, ULONG count)
{
if (m_mediaTypeToken != token) {
return VFW_E_ENUM_OUT_OF_SYNC;
} else {
*index = qMin<int>(*index + count, m_mediaTypes.size());
return *index < m_mediaTypes.size() ? S_OK : S_FALSE;
}
}
HRESULT DirectShowMediaTypeList::cloneMediaType(int token, int index, IEnumMediaTypes **enumeration)
{
if (m_mediaTypeToken != token) {
return VFW_E_ENUM_OUT_OF_SYNC;
} else {
*enumeration = new DirectShowMediaTypeEnum(this, token, index);
return S_OK;
}
}

View File

@@ -0,0 +1,69 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DIRECTSHOWMEDIATYPELIST_H
#define DIRECTSHOWMEDIATYPELIST_H
#include <QtCore/qvector.h>
#include <dshow.h>
class DirectShowMediaTypeList : public IUnknown
{
public:
DirectShowMediaTypeList();
IEnumMediaTypes *createMediaTypeEnum();
void setMediaTypes(const QVector<AM_MEDIA_TYPE> &types);
virtual int currentMediaTypeToken();
virtual HRESULT nextMediaType(
int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount);
virtual HRESULT skipMediaType(int token, int *index, ULONG count);
virtual HRESULT cloneMediaType(int token, int index, IEnumMediaTypes **enumeration);
private:
int m_mediaTypeToken;
QVector<AM_MEDIA_TYPE> m_mediaTypes;
};
#endif

View File

@@ -0,0 +1,352 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <dshow.h>
#include <initguid.h>
#include <qnetwork.h>
#include "directshowmetadatacontrol.h"
#include "directshowplayerservice.h"
#include <QtCore/qcoreapplication.h>
#ifndef QT_NO_WMSDK
namespace
{
struct QWMMetaDataKeyLookup
{
QtMultimediaKit::MetaData key;
const wchar_t *token;
};
}
static const QWMMetaDataKeyLookup qt_wmMetaDataKeys[] =
{
{ QtMultimediaKit::Title, L"Title" },
{ QtMultimediaKit::SubTitle, L"WM/SubTitle" },
{ QtMultimediaKit::Author, L"Author" },
{ QtMultimediaKit::Comment, L"Comment" },
{ QtMultimediaKit::Description, L"Description" },
{ QtMultimediaKit::Category, L"WM/Category" },
{ QtMultimediaKit::Genre, L"WM/Genre" },
//{ QtMultimediaKit::Date, 0 },
{ QtMultimediaKit::Year, L"WM/Year" },
{ QtMultimediaKit::UserRating, L"UserRating" },
//{ QtMultimediaKit::MetaDatawords, 0 },
{ QtMultimediaKit::Language, L"Language" },
{ QtMultimediaKit::Publisher, L"WM/Publisher" },
{ QtMultimediaKit::Copyright, L"Copyright" },
{ QtMultimediaKit::ParentalRating, L"ParentalRating" },
{ QtMultimediaKit::RatingOrganisation, L"RatingOrganisation" },
// Media
{ QtMultimediaKit::Size, L"FileSize" },
{ QtMultimediaKit::MediaType, L"MediaType" },
{ QtMultimediaKit::Duration, L"Duration" },
// Audio
{ QtMultimediaKit::AudioBitRate, L"AudioBitRate" },
{ QtMultimediaKit::AudioCodec, L"AudioCodec" },
{ QtMultimediaKit::ChannelCount, L"ChannelCount" },
{ QtMultimediaKit::SampleRate, L"Frequency" },
// Music
{ QtMultimediaKit::AlbumTitle, L"WM/AlbumTitle" },
{ QtMultimediaKit::AlbumArtist, L"WM/AlbumArtist" },
{ QtMultimediaKit::ContributingArtist, L"Author" },
{ QtMultimediaKit::Composer, L"WM/Composer" },
{ QtMultimediaKit::Conductor, L"WM/Conductor" },
{ QtMultimediaKit::Lyrics, L"WM/Lyrics" },
{ QtMultimediaKit::Mood, L"WM/Mood" },
{ QtMultimediaKit::TrackNumber, L"WM/TrackNumber" },
//{ QtMultimediaKit::TrackCount, 0 },
//{ QtMultimediaKit::CoverArtUriSmall, 0 },
//{ QtMultimediaKit::CoverArtUriLarge, 0 },
// Image/Video
//{ QtMultimediaKit::Resolution, 0 },
//{ QtMultimediaKit::PixelAspectRatio, 0 },
// Video
//{ QtMultimediaKit::FrameRate, 0 },
{ QtMultimediaKit::VideoBitRate, L"VideoBitRate" },
{ QtMultimediaKit::VideoCodec, L"VideoCodec" },
//{ QtMultimediaKit::PosterUri, 0 },
// Movie
{ QtMultimediaKit::ChapterNumber, L"ChapterNumber" },
{ QtMultimediaKit::Director, L"WM/Director" },
{ QtMultimediaKit::LeadPerformer, L"LeadPerformer" },
{ QtMultimediaKit::Writer, L"WM/Writer" },
// Photos
{ QtMultimediaKit::CameraManufacturer, L"CameraManufacturer" },
{ QtMultimediaKit::CameraModel, L"CameraModel" },
{ QtMultimediaKit::Event, L"Event" },
{ QtMultimediaKit::Subject, L"Subject" }
};
static QVariant getValue(IWMHeaderInfo *header, const wchar_t *key)
{
WORD streamNumber = 0;
WMT_ATTR_DATATYPE type = WMT_TYPE_DWORD;
WORD size = 0;
if (header->GetAttributeByName(&streamNumber, key, &type, 0, &size) == S_OK) {
switch (type) {
case WMT_TYPE_DWORD:
if (size == sizeof(DWORD)) {
DWORD word;
if (header->GetAttributeByName(
&streamNumber,
key,
&type,
reinterpret_cast<BYTE *>(&word),
&size) == S_OK) {
return int(word);
}
}
break;
case WMT_TYPE_STRING:
{
QString string;
string.resize(size / 2 - 1);
if (header->GetAttributeByName(
&streamNumber,
key,
&type,
reinterpret_cast<BYTE *>(const_cast<ushort *>(string.utf16())),
&size) == S_OK) {
return string;
}
}
break;
case WMT_TYPE_BINARY:
{
QByteArray bytes;
bytes.resize(size);
if (header->GetAttributeByName(
&streamNumber,
key,
&type,
reinterpret_cast<BYTE *>(bytes.data()),
&size) == S_OK) {
return bytes;
}
}
break;
case WMT_TYPE_BOOL:
if (size == sizeof(DWORD)) {
DWORD word;
if (header->GetAttributeByName(
&streamNumber,
key,
&type,
reinterpret_cast<BYTE *>(&word),
&size) == S_OK) {
return bool(word);
}
}
break;
case WMT_TYPE_QWORD:
if (size == sizeof(QWORD)) {
QWORD word;
if (header->GetAttributeByName(
&streamNumber,
key,
&type,
reinterpret_cast<BYTE *>(&word),
&size) == S_OK) {
return qint64(word);
}
}
break;
case WMT_TYPE_WORD:
if (size == sizeof(WORD)){
WORD word;
if (header->GetAttributeByName(
&streamNumber,
key,
&type,
reinterpret_cast<BYTE *>(&word),
&size) == S_OK) {
return short(word);
}
}
break;
case WMT_TYPE_GUID:
if (size == 16) {
}
break;
default:
break;
}
}
return QVariant();
}
#endif
DirectShowMetaDataControl::DirectShowMetaDataControl(QObject *parent)
: QMetaDataReaderControl(parent)
, m_content(0)
#ifndef QT_NO_WMSDK
, m_headerInfo(0)
#endif
{
}
DirectShowMetaDataControl::~DirectShowMetaDataControl()
{
}
bool DirectShowMetaDataControl::isMetaDataAvailable() const
{
#ifndef QT_NO_WMSDK
return m_content || m_headerInfo;
#else
return m_content;
#endif
}
QVariant DirectShowMetaDataControl::metaData(QtMultimediaKit::MetaData key) const
{
QVariant value;
#ifndef QT_NO_WMSDK
if (m_headerInfo) {
static const int count = sizeof(qt_wmMetaDataKeys) / sizeof(QWMMetaDataKeyLookup);
for (int i = 0; i < count; ++i) {
if (qt_wmMetaDataKeys[i].key == key) {
value = getValue(m_headerInfo, qt_wmMetaDataKeys[i].token);
break;
}
}
} else if (m_content) {
#else
if (m_content) {
#endif
BSTR string = 0;
switch (key) {
case QtMultimediaKit::Author:
m_content->get_AuthorName(&string);
break;
case QtMultimediaKit::Title:
m_content->get_Title(&string);
break;
case QtMultimediaKit::ParentalRating:
m_content->get_Rating(&string);
break;
case QtMultimediaKit::Description:
m_content->get_Description(&string);
break;
case QtMultimediaKit::Copyright:
m_content->get_Copyright(&string);
break;
default:
break;
}
if (string) {
value = QString::fromUtf16(reinterpret_cast<ushort *>(string), ::SysStringLen(string));
::SysFreeString(string);
}
}
return value;
}
QList<QtMultimediaKit::MetaData> DirectShowMetaDataControl::availableMetaData() const
{
return QList<QtMultimediaKit::MetaData>();
}
QVariant DirectShowMetaDataControl::extendedMetaData(const QString &) const
{
return QVariant();
}
QStringList DirectShowMetaDataControl::availableExtendedMetaData() const
{
return QStringList();
}
void DirectShowMetaDataControl::updateGraph(IFilterGraph2 *graph, IBaseFilter *source)
{
if (m_content)
m_content->Release();
if (!graph || graph->QueryInterface(
IID_IAMMediaContent, reinterpret_cast<void **>(&m_content)) != S_OK) {
m_content = 0;
}
#ifdef QT_NO_WMSDK
Q_UNUSED(source);
#else
if (m_headerInfo)
m_headerInfo->Release();
m_headerInfo = com_cast<IWMHeaderInfo>(source, IID_IWMHeaderInfo);
#endif
// DirectShowMediaPlayerService holds a lock at this point so defer emitting signals to a later
// time.
QCoreApplication::postEvent(this, new QEvent(QEvent::Type(MetaDataChanged)));
}
void DirectShowMetaDataControl::customEvent(QEvent *event)
{
if (event->type() == QEvent::Type(MetaDataChanged)) {
event->accept();
emit metaDataChanged();
#ifndef QT_NO_WMSDK
emit metaDataAvailableChanged(m_content || m_headerInfo);
#else
emit metaDataAvailableChanged(m_content);
#endif
} else {
QMetaDataReaderControl::customEvent(event);
}
}

View File

@@ -0,0 +1,93 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DIRECTSHOWMETADATACONTROL_H
#define DIRECTSHOWMETADATACONTROL_H
#include <qmetadatareadercontrol.h>
#include "directshowglobal.h"
#include <qnetwork.h>
#ifndef QT_NO_WMSDK
#include <wmsdk.h>
#endif
#include <QtCore/qcoreevent.h>
class DirectShowPlayerService;
QT_USE_NAMESPACE
class DirectShowMetaDataControl : public QMetaDataReaderControl
{
Q_OBJECT
public:
DirectShowMetaDataControl(QObject *parent = 0);
~DirectShowMetaDataControl();
bool isMetaDataAvailable() const;
QVariant metaData(QtMultimediaKit::MetaData key) const;
QList<QtMultimediaKit::MetaData> availableMetaData() const;
QVariant extendedMetaData(const QString &key) const;
QStringList availableExtendedMetaData() const;
void updateGraph(IFilterGraph2 *graph, IBaseFilter *source);
protected:
void customEvent(QEvent *event);
private:
enum Event
{
MetaDataChanged = QEvent::User
};
IAMMediaContent *m_content;
#ifndef QT_NO_WMSDK
IWMHeaderInfo *m_headerInfo;
#endif
};
#endif

View File

@@ -0,0 +1,134 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "directshowpinenum.h"
DirectShowPinEnum::DirectShowPinEnum(const QList<IPin *> &pins)
: m_ref(1)
, m_pins(pins)
, m_index(0)
{
foreach (IPin *pin, m_pins)
pin->AddRef();
}
DirectShowPinEnum::~DirectShowPinEnum()
{
foreach (IPin *pin, m_pins)
pin->Release();
}
HRESULT DirectShowPinEnum::QueryInterface(REFIID riid, void **ppvObject)
{
if (riid == IID_IUnknown
|| riid == IID_IEnumPins) {
AddRef();
*ppvObject = static_cast<IEnumPins *>(this);
return S_OK;
} else {
*ppvObject = 0;
return E_NOINTERFACE;
}
}
ULONG DirectShowPinEnum::AddRef()
{
return InterlockedIncrement(&m_ref);
}
ULONG DirectShowPinEnum::Release()
{
ULONG ref = InterlockedDecrement(&m_ref);
if (ref == 0) {
delete this;
}
return ref;
}
HRESULT DirectShowPinEnum::Next(ULONG cPins, IPin **ppPins, ULONG *pcFetched)
{
if (ppPins && (pcFetched || cPins == 1)) {
ULONG count = qBound<ULONG>(0, cPins, m_pins.count() - m_index);
for (ULONG i = 0; i < count; ++i, ++m_index) {
ppPins[i] = m_pins.at(m_index);
ppPins[i]->AddRef();
}
if (pcFetched)
*pcFetched = count;
return count == cPins ? S_OK : S_FALSE;
} else {
return E_POINTER;
}
}
HRESULT DirectShowPinEnum::Skip(ULONG cPins)
{
m_index = qMin(int(m_index + cPins), m_pins.count());
return m_index < m_pins.count() ? S_OK : S_FALSE;
}
HRESULT DirectShowPinEnum::Reset()
{
m_index = 0;
return S_OK;
}
HRESULT DirectShowPinEnum::Clone(IEnumPins **ppEnum)
{
if (ppEnum) {
*ppEnum = new DirectShowPinEnum(m_pins);
return S_OK;
} else {
return E_POINTER;
}
}

View File

@@ -0,0 +1,72 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DIRECTSHOWPINENUM_H
#define DIRECTSHOWPINENUM_H
#include <QtCore/qlist.h>
#include <dshow.h>
class DirectShowPinEnum : public IEnumPins
{
public:
DirectShowPinEnum(const QList<IPin *> &pins);
~DirectShowPinEnum();
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
// IEnumPins
HRESULT STDMETHODCALLTYPE Next(ULONG cPins, IPin **ppPins, ULONG *pcFetched);
HRESULT STDMETHODCALLTYPE Skip(ULONG cPins);
HRESULT STDMETHODCALLTYPE Reset();
HRESULT STDMETHODCALLTYPE Clone(IEnumPins **ppEnum);
private:
LONG m_ref;
QList<IPin *> m_pins;
int m_index;
};
#endif

View File

@@ -0,0 +1,405 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "directshowplayercontrol.h"
#include "directshowplayerservice.h"
#include <QtCore/qcoreapplication.h>
#include <QtCore/qmath.h>
static int volumeToDecibels(int volume)
{
if (volume == 0) {
return -10000;
} else if (volume == 100) {
return 0;
#ifdef QT_USE_MATH_H_FLOATS
} else if (sizeof(qreal) == sizeof(float)) {
return qRound(::log10f(float(volume) / 100) * 5000);
#endif
} else {
return qRound(::log10(qreal(volume) / 100) * 5000);
}
}
static int decibelsToVolume(int dB)
{
if (dB == -10000) {
return 0;
} else if (dB == 0) {
return 100;
} else {
return qRound(100 * qPow(10, qreal(dB) / 5000));
}
}
DirectShowPlayerControl::DirectShowPlayerControl(DirectShowPlayerService *service, QObject *parent)
: QMediaPlayerControl(parent)
, m_service(service)
, m_audio(0)
, m_updateProperties(0)
, m_state(QMediaPlayer::StoppedState)
, m_status(QMediaPlayer::NoMedia)
, m_error(QMediaPlayer::NoError)
, m_streamTypes(0)
, m_muteVolume(-1)
, m_position(0)
, m_duration(0)
, m_playbackRate(0)
, m_seekable(false)
{
}
DirectShowPlayerControl::~DirectShowPlayerControl()
{
if (m_audio)
m_audio->Release();
}
QMediaPlayer::State DirectShowPlayerControl::state() const
{
return m_state;
}
QMediaPlayer::MediaStatus DirectShowPlayerControl::mediaStatus() const
{
return m_status;
}
qint64 DirectShowPlayerControl::duration() const
{
return m_duration;
}
qint64 DirectShowPlayerControl::position() const
{
return const_cast<qint64 &>(m_position) = m_service->position();
}
void DirectShowPlayerControl::setPosition(qint64 position)
{
m_service->seek(position);
}
int DirectShowPlayerControl::volume() const
{
if (m_muteVolume >= 0) {
return m_muteVolume;
} else if (m_audio) {
long dB = 0;
m_audio->get_Volume(&dB);
return decibelsToVolume(dB);
} else {
return 0;
}
}
void DirectShowPlayerControl::setVolume(int volume)
{
int boundedVolume = qBound(0, volume, 100);
if (m_muteVolume >= 0) {
m_muteVolume = boundedVolume;
emit volumeChanged(m_muteVolume);
} else if (m_audio) {
m_audio->put_Volume(volumeToDecibels(volume));
emit volumeChanged(boundedVolume);
}
}
bool DirectShowPlayerControl::isMuted() const
{
return m_muteVolume >= 0;
}
void DirectShowPlayerControl::setMuted(bool muted)
{
if (muted && m_muteVolume < 0) {
if (m_audio) {
long dB = 0;
m_audio->get_Volume(&dB);
m_muteVolume = decibelsToVolume(dB);
m_audio->put_Volume(-10000);
} else {
m_muteVolume = 0;
}
emit mutedChanged(muted);
} else if (!muted && m_muteVolume >= 0) {
if (m_audio) {
m_audio->put_Volume(volumeToDecibels(m_muteVolume));
}
m_muteVolume = -1;
emit mutedChanged(muted);
}
}
int DirectShowPlayerControl::bufferStatus() const
{
return m_service->bufferStatus();
}
bool DirectShowPlayerControl::isAudioAvailable() const
{
return m_streamTypes & DirectShowPlayerService::AudioStream;
}
bool DirectShowPlayerControl::isVideoAvailable() const
{
return m_streamTypes & DirectShowPlayerService::VideoStream;
}
bool DirectShowPlayerControl::isSeekable() const
{
return m_seekable;
}
QMediaTimeRange DirectShowPlayerControl::availablePlaybackRanges() const
{
return m_service->availablePlaybackRanges();
}
qreal DirectShowPlayerControl::playbackRate() const
{
return m_playbackRate;
}
void DirectShowPlayerControl::setPlaybackRate(qreal rate)
{
if (m_playbackRate != rate) {
m_service->setRate(rate);
emit playbackRateChanged(m_playbackRate = rate);
}
}
QMediaContent DirectShowPlayerControl::media() const
{
return m_media;
}
const QIODevice *DirectShowPlayerControl::mediaStream() const
{
return m_stream;
}
void DirectShowPlayerControl::setMedia(const QMediaContent &media, QIODevice *stream)
{
m_media = media;
m_stream = stream;
m_updateProperties &= PlaybackRateProperty;
m_service->load(media, stream);
emit mediaChanged(m_media);
emitPropertyChanges();
}
void DirectShowPlayerControl::play()
{
if (m_status == QMediaPlayer::NoMedia)
return;
if (m_status == QMediaPlayer::InvalidMedia) {
setMedia(m_media, m_stream);
if (m_error != QMediaPlayer::NoError)
return;
}
m_service->play();
emit stateChanged(m_state = QMediaPlayer::PlayingState);
}
void DirectShowPlayerControl::pause()
{
if (m_status == QMediaPlayer::NoMedia)
return;
if (m_status == QMediaPlayer::InvalidMedia) {
setMedia(m_media, m_stream);
if (m_error != QMediaPlayer::NoError)
return;
}
m_service->pause();
emit stateChanged(m_state = QMediaPlayer::PausedState);
}
void DirectShowPlayerControl::stop()
{
m_service->stop();
emit stateChanged(m_state = QMediaPlayer::StoppedState);
}
void DirectShowPlayerControl::customEvent(QEvent *event)
{
if (event->type() == QEvent::Type(PropertiesChanged)) {
emitPropertyChanges();
event->accept();
} else {
QMediaPlayerControl::customEvent(event);
}
}
void DirectShowPlayerControl::emitPropertyChanges()
{
int properties = m_updateProperties;
m_updateProperties = 0;
if ((properties & ErrorProperty) && m_error != QMediaPlayer::NoError)
emit error(m_error, m_errorString);
if (properties & PlaybackRateProperty)
emit playbackRateChanged(m_playbackRate);
if (properties & StreamTypesProperty) {
emit audioAvailableChanged(m_streamTypes & DirectShowPlayerService::AudioStream);
emit videoAvailableChanged(m_streamTypes & DirectShowPlayerService::VideoStream);
}
if (properties & PositionProperty)
emit positionChanged(m_position);
if (properties & DurationProperty)
emit durationChanged(m_duration);
if (properties & SeekableProperty)
emit seekableChanged(m_seekable);
if (properties & StatusProperty)
emit mediaStatusChanged(m_status);
if (properties & StateProperty)
emit stateChanged(m_state);
}
void DirectShowPlayerControl::scheduleUpdate(int properties)
{
if (m_updateProperties == 0)
QCoreApplication::postEvent(this, new QEvent(QEvent::Type(PropertiesChanged)));
m_updateProperties |= properties;
}
void DirectShowPlayerControl::updateState(QMediaPlayer::State state)
{
if (m_state != state) {
m_state = state;
scheduleUpdate(StateProperty);
}
}
void DirectShowPlayerControl::updateStatus(QMediaPlayer::MediaStatus status)
{
if (m_status != status) {
m_status = status;
scheduleUpdate(StatusProperty);
}
}
void DirectShowPlayerControl::updateMediaInfo(qint64 duration, int streamTypes, bool seekable)
{
int properties = 0;
if (m_duration != duration) {
m_duration = duration;
properties |= DurationProperty;
}
if (m_streamTypes != streamTypes) {
m_streamTypes = streamTypes;
properties |= StreamTypesProperty;
}
if (m_seekable != seekable) {
m_seekable = seekable;
properties |= SeekableProperty;
}
if (properties != 0)
scheduleUpdate(properties);
}
void DirectShowPlayerControl::updatePlaybackRate(qreal rate)
{
if (m_playbackRate != rate) {
m_playbackRate = rate;
scheduleUpdate(PlaybackRateProperty);
}
}
void DirectShowPlayerControl::updateAudioOutput(IBaseFilter *filter)
{
if (m_audio)
m_audio->Release();
m_audio = com_cast<IBasicAudio>(filter, IID_IBasicAudio);
}
void DirectShowPlayerControl::updateError(QMediaPlayer::Error error, const QString &errorString)
{
m_error = error;
m_errorString = errorString;
if (m_error != QMediaPlayer::NoError)
scheduleUpdate(ErrorProperty);
}
void DirectShowPlayerControl::updatePosition(qint64 position)
{
if (m_position != position) {
m_position = position;
scheduleUpdate(PositionProperty);
}
}

View File

@@ -0,0 +1,146 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DIRECTSHOWPLAYERCONTROL_H
#define DIRECTSHOWPLAYERCONTROL_H
#include "qmediacontent.h"
#include "qmediaplayercontrol.h"
#include <QtCore/qcoreevent.h>
#include "directshowplayerservice.h"
QT_USE_NAMESPACE
class DirectShowPlayerControl : public QMediaPlayerControl
{
Q_OBJECT
public:
DirectShowPlayerControl(DirectShowPlayerService *service, QObject *parent = 0);
~DirectShowPlayerControl();
QMediaPlayer::State state() const;
QMediaPlayer::MediaStatus mediaStatus() const;
qint64 duration() const;
qint64 position() const;
void setPosition(qint64 position);
int volume() const;
void setVolume(int volume);
bool isMuted() const;
void setMuted(bool muted);
int bufferStatus() const;
bool isAudioAvailable() const;
bool isVideoAvailable() const;
bool isSeekable() const;
QMediaTimeRange availablePlaybackRanges() const;
qreal playbackRate() const;
void setPlaybackRate(qreal rate);
QMediaContent media() const;
const QIODevice *mediaStream() const;
void setMedia(const QMediaContent &media, QIODevice *stream);
void play();
void pause();
void stop();
void updateState(QMediaPlayer::State state);
void updateStatus(QMediaPlayer::MediaStatus status);
void updateMediaInfo(qint64 duration, int streamTypes, bool seekable);
void updatePlaybackRate(qreal rate);
void updateAudioOutput(IBaseFilter *filter);
void updateError(QMediaPlayer::Error error, const QString &errorString);
void updatePosition(qint64 position);
protected:
void customEvent(QEvent *event);
private:
enum Properties
{
StateProperty = 0x01,
StatusProperty = 0x02,
StreamTypesProperty = 0x04,
DurationProperty = 0x08,
PlaybackRateProperty = 0x10,
SeekableProperty = 0x20,
ErrorProperty = 0x40,
PositionProperty = 0x80
};
enum Event
{
PropertiesChanged = QEvent::User
};
void scheduleUpdate(int properties);
void emitPropertyChanges();
DirectShowPlayerService *m_service;
IBasicAudio *m_audio;
QIODevice *m_stream;
int m_updateProperties;
QMediaPlayer::State m_state;
QMediaPlayer::MediaStatus m_status;
QMediaPlayer::Error m_error;
int m_streamTypes;
int m_muteVolume;
qint64 m_position;
qint64 m_duration;
qreal m_playbackRate;
bool m_seekable;
QMediaContent m_media;
QString m_errorString;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,219 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DIRECTSHOWPLAYERSERVICE_H
#define DIRECTSHOWPLAYERSERVICE_H
#include "qmediaplayer.h"
#include "qmediaresource.h"
#include "qmediaservice.h"
#include "qmediatimerange.h"
#include "directshoweventloop.h"
#include "directshowglobal.h"
#include <QtCore/qcoreevent.h>
#include <QtCore/qmutex.h>
#include <QtCore/qurl.h>
#include <QtCore/qwaitcondition.h>
class DirectShowAudioEndpointControl;
class DirectShowMetaDataControl;
class DirectShowPlayerControl;
class DirectShowVideoRendererControl;
#ifndef Q_WS_SIMULATOR
class Vmr9VideoWindowControl;
#endif
QT_BEGIN_NAMESPACE
class QMediaContent;
QT_END_NAMESPACE
QT_USE_NAMESPACE
class DirectShowPlayerService : public QMediaService
{
Q_OBJECT
public:
enum StreamType
{
AudioStream = 0x01,
VideoStream = 0x02
};
DirectShowPlayerService(QObject *parent = 0);
~DirectShowPlayerService();
QMediaControl* requestControl(const char *name);
void releaseControl(QMediaControl *control);
void load(const QMediaContent &media, QIODevice *stream);
void play();
void pause();
void stop();
qint64 position() const;
QMediaTimeRange availablePlaybackRanges() const;
void seek(qint64 position);
void setRate(qreal rate);
int bufferStatus() const;
void setAudioOutput(IBaseFilter *filter);
void setVideoOutput(IBaseFilter *filter);
protected:
void customEvent(QEvent *event);
private Q_SLOTS:
void videoOutputChanged();
private:
void releaseGraph();
void updateStatus();
int findStreamTypes(IBaseFilter *source) const;
int findStreamType(IPin *pin) const;
bool isConnected(IBaseFilter *filter, PIN_DIRECTION direction) const;
IBaseFilter *getConnected(IBaseFilter *filter, PIN_DIRECTION direction) const;
void run();
void doSetUrlSource(QMutexLocker *locker);
void doSetStreamSource(QMutexLocker *locker);
void doRender(QMutexLocker *locker);
void doFinalizeLoad(QMutexLocker *locker);
void doSetRate(QMutexLocker *locker);
void doSeek(QMutexLocker *locker);
void doPlay(QMutexLocker *locker);
void doPause(QMutexLocker *locker);
void doStop(QMutexLocker *locker);
void doReleaseAudioOutput(QMutexLocker *locker);
void doReleaseVideoOutput(QMutexLocker *locker);
void doReleaseGraph(QMutexLocker *locker);
void graphEvent(QMutexLocker *locker);
enum Task
{
Shutdown = 0x0001,
SetUrlSource = 0x0002,
SetStreamSource = 0x0004,
SetSource = SetUrlSource | SetStreamSource,
SetAudioOutput = 0x0008,
SetVideoOutput = 0x0010,
SetOutputs = SetAudioOutput | SetVideoOutput,
Render = 0x0020,
FinalizeLoad = 0x0040,
SetRate = 0x0080,
Seek = 0x0100,
Play = 0x0200,
Pause = 0x0400,
Stop = 0x0800,
ReleaseGraph = 0x1000,
ReleaseAudioOutput = 0x2000,
ReleaseVideoOutput = 0x4000,
ReleaseFilters = ReleaseGraph | ReleaseAudioOutput | ReleaseVideoOutput
};
enum Event
{
FinalizedLoad = QEvent::User,
Error,
RateChange,
Started,
Paused,
DurationChange,
StatusChange,
EndOfMedia,
PositionChange
};
enum GraphStatus
{
NoMedia,
Loading,
Loaded,
InvalidMedia
};
DirectShowPlayerControl *m_playerControl;
DirectShowMetaDataControl *m_metaDataControl;
DirectShowVideoRendererControl *m_videoRendererControl;
#ifndef Q_WS_SIMULATOR
Vmr9VideoWindowControl *m_videoWindowControl;
#endif
DirectShowAudioEndpointControl *m_audioEndpointControl;
QThread *m_taskThread;
DirectShowEventLoop *m_loop;
int m_pendingTasks;
int m_executingTask;
int m_executedTasks;
HANDLE m_taskHandle;
HANDLE m_eventHandle;
GraphStatus m_graphStatus;
QMediaPlayer::Error m_error;
QIODevice *m_stream;
IFilterGraph2 *m_graph;
IBaseFilter *m_source;
IBaseFilter *m_audioOutput;
IBaseFilter *m_videoOutput;
int m_streamTypes;
qreal m_rate;
qint64 m_position;
qint64 m_duration;
bool m_buffering;
bool m_seekable;
bool m_atEnd;
QMediaTimeRange m_playbackRange;
QUrl m_url;
QMediaResourceList m_resources;
QString m_errorString;
QMutex m_mutex;
friend class DirectShowPlayerServiceThread;
};
#endif

View File

@@ -0,0 +1,437 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "directshowsamplescheduler.h"
#include <QtCore/qcoreapplication.h>
#include <QtCore/qcoreevent.h>
class DirectShowTimedSample
{
public:
DirectShowTimedSample(IMediaSample *sample)
: m_next(0)
, m_sample(sample)
, m_cookie(0)
, m_lastSample(false)
{
m_sample->AddRef();
}
~DirectShowTimedSample()
{
m_sample->Release();
}
IMediaSample *sample() const { return m_sample; }
DirectShowTimedSample *nextSample() const { return m_next; }
void setNextSample(DirectShowTimedSample *sample) { Q_ASSERT(!m_next); m_next = sample; }
DirectShowTimedSample *remove() {
DirectShowTimedSample *next = m_next; delete this; return next; }
bool schedule(IReferenceClock *clock, REFERENCE_TIME startTime, HANDLE handle);
void unschedule(IReferenceClock *clock);
bool isReady(IReferenceClock *clock) const;
bool isLast() const { return m_lastSample; }
void setLast() { m_lastSample = true; }
private:
DirectShowTimedSample *m_next;
IMediaSample *m_sample;
DWORD_PTR m_cookie;
bool m_lastSample;
};
bool DirectShowTimedSample::schedule(
IReferenceClock *clock, REFERENCE_TIME startTime, HANDLE handle)
{
REFERENCE_TIME sampleStartTime;
REFERENCE_TIME sampleEndTime;
if (m_sample->GetTime(&sampleStartTime, &sampleEndTime) == S_OK) {
if (clock->AdviseTime(
startTime, sampleStartTime, reinterpret_cast<HEVENT>(handle), &m_cookie) == S_OK) {
return true;
}
}
return false;
}
void DirectShowTimedSample::unschedule(IReferenceClock *clock)
{
clock->Unadvise(m_cookie);
}
bool DirectShowTimedSample::isReady(IReferenceClock *clock) const
{
REFERENCE_TIME sampleStartTime;
REFERENCE_TIME sampleEndTime;
REFERENCE_TIME currentTime;
if (m_sample->GetTime(&sampleStartTime, &sampleEndTime) == S_OK) {
if (clock->GetTime(&currentTime) == S_OK)
return currentTime >= sampleStartTime;
}
return true;
}
DirectShowSampleScheduler::DirectShowSampleScheduler(IUnknown *pin, QObject *parent)
: QObject(parent)
, m_pin(pin)
, m_clock(0)
, m_allocator(0)
, m_head(0)
, m_tail(0)
, m_maximumSamples(1)
, m_state(Stopped)
, m_startTime(0)
, m_timeoutEvent(::CreateEvent(0, 0, 0, 0))
, m_flushEvent(::CreateEvent(0, 0, 0, 0))
{
m_semaphore.release(m_maximumSamples);
}
DirectShowSampleScheduler::~DirectShowSampleScheduler()
{
::CloseHandle(m_timeoutEvent);
::CloseHandle(m_flushEvent);
Q_ASSERT(!m_clock);
Q_ASSERT(!m_allocator);
}
HRESULT DirectShowSampleScheduler::QueryInterface(REFIID riid, void **ppvObject)
{
return m_pin->QueryInterface(riid, ppvObject);
}
ULONG DirectShowSampleScheduler::AddRef()
{
return m_pin->AddRef();
}
ULONG DirectShowSampleScheduler::Release()
{
return m_pin->Release();
}
// IMemInputPin
HRESULT DirectShowSampleScheduler::GetAllocator(IMemAllocator **ppAllocator)
{
if (!ppAllocator) {
return E_POINTER;
} else {
QMutexLocker locker(&m_mutex);
if (!m_allocator) {
return VFW_E_NO_ALLOCATOR;
} else {
*ppAllocator = m_allocator;
return S_OK;
}
}
}
HRESULT DirectShowSampleScheduler::NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly)
{
Q_UNUSED(bReadOnly);
HRESULT hr;
ALLOCATOR_PROPERTIES properties;
if (!pAllocator) {
if (m_allocator)
m_allocator->Release();
m_allocator = 0;
return S_OK;
} else if ((hr = pAllocator->GetProperties(&properties)) != S_OK) {
return hr;
} else {
if (properties.cBuffers == 1) {
ALLOCATOR_PROPERTIES actual;
properties.cBuffers = 2;
if ((hr = pAllocator->SetProperties(&properties, &actual)) != S_OK)
return hr;
}
QMutexLocker locker(&m_mutex);
if (m_allocator)
m_allocator->Release();
m_allocator = pAllocator;
m_allocator->AddRef();
return S_OK;
}
}
HRESULT DirectShowSampleScheduler::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps)
{
if (!pProps)
return E_POINTER;
pProps->cBuffers = 2;
return S_OK;
}
HRESULT DirectShowSampleScheduler::Receive(IMediaSample *pSample)
{
if (!pSample)
return E_POINTER;
m_semaphore.acquire(1);
QMutexLocker locker(&m_mutex);
if (m_state & Flushing) {
m_semaphore.release(1);
return S_FALSE;
} else if (m_state == Stopped) {
m_semaphore.release();
return VFW_E_WRONG_STATE;
} else {
DirectShowTimedSample *timedSample = new DirectShowTimedSample(pSample);
if (m_tail)
m_tail->setNextSample(timedSample);
else
m_head = timedSample;
m_tail = timedSample;
if (m_state == Running) {
if (!timedSample->schedule(m_clock, m_startTime, m_timeoutEvent)) {
// Timing information is unavailable, so schedule frames immediately.
QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
} else {
locker.unlock();
HANDLE handles[] = { m_flushEvent, m_timeoutEvent };
DWORD result = ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
locker.relock();
if (result == WAIT_OBJECT_0 + 1)
QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
}
} else if (m_tail == m_head) {
// If this is the first frame make it available.
QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
if (m_state == Paused) {
::ResetEvent(m_timeoutEvent);
locker.unlock();
HANDLE handles[] = { m_flushEvent, m_timeoutEvent };
::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
locker.relock();
}
}
return S_OK;
}
}
HRESULT DirectShowSampleScheduler::ReceiveMultiple(
IMediaSample **pSamples, long nSamples, long *nSamplesProcessed)
{
if (!pSamples || !nSamplesProcessed)
return E_POINTER;
for (*nSamplesProcessed = 0; *nSamplesProcessed < nSamples; ++(*nSamplesProcessed)) {
HRESULT hr = Receive(pSamples[*nSamplesProcessed]);
if (hr != S_OK)
return hr;
}
return S_OK;
}
HRESULT DirectShowSampleScheduler::ReceiveCanBlock()
{
return S_OK;
}
void DirectShowSampleScheduler::run(REFERENCE_TIME startTime)
{
QMutexLocker locker(&m_mutex);
m_state = (m_state & Flushing) | Running;
m_startTime = startTime;
for (DirectShowTimedSample *sample = m_head; sample; sample = sample->nextSample()) {
sample->schedule(m_clock, m_startTime, m_timeoutEvent);
}
if (!(m_state & Flushing))
::ResetEvent(m_flushEvent);
if (!m_head)
::SetEvent(m_timeoutEvent);
}
void DirectShowSampleScheduler::pause()
{
QMutexLocker locker(&m_mutex);
m_state = (m_state & Flushing) | Paused;
for (DirectShowTimedSample *sample = m_head; sample; sample = sample->nextSample())
sample->unschedule(m_clock);
if (!(m_state & Flushing))
::ResetEvent(m_flushEvent);
}
void DirectShowSampleScheduler::stop()
{
QMutexLocker locker(&m_mutex);
m_state = m_state & Flushing;
for (DirectShowTimedSample *sample = m_head; sample; sample = sample->remove()) {
sample->unschedule(m_clock);
m_semaphore.release(1);
}
m_head = 0;
m_tail = 0;
::SetEvent(m_flushEvent);
}
void DirectShowSampleScheduler::setFlushing(bool flushing)
{
QMutexLocker locker(&m_mutex);
const bool isFlushing = m_state & Flushing;
if (isFlushing != flushing) {
if (flushing) {
m_state |= Flushing;
for (DirectShowTimedSample *sample = m_head; sample; sample = sample->remove()) {
sample->unschedule(m_clock);
m_semaphore.release(1);
}
m_head = 0;
m_tail = 0;
::SetEvent(m_flushEvent);
} else {
m_state &= ~Flushing;
if (m_state != Stopped)
::ResetEvent(m_flushEvent);
}
}
}
void DirectShowSampleScheduler::setClock(IReferenceClock *clock)
{
QMutexLocker locker(&m_mutex);
if (m_clock)
m_clock->Release();
m_clock = clock;
if (m_clock)
m_clock->AddRef();
}
IMediaSample *DirectShowSampleScheduler::takeSample(bool *eos)
{
QMutexLocker locker(&m_mutex);
if (m_head && m_head->isReady(m_clock)) {
IMediaSample *sample = m_head->sample();
sample->AddRef();
*eos = m_head->isLast();
m_head = m_head->remove();
if (!m_head)
m_tail = 0;
m_semaphore.release(1);
return sample;
} else {
return 0;
}
}
bool DirectShowSampleScheduler::scheduleEndOfStream()
{
QMutexLocker locker(&m_mutex);
if (m_tail) {
m_tail->setLast();
return true;
} else {
return false;
}
}
bool DirectShowSampleScheduler::event(QEvent *event)
{
if (event->type() == QEvent::UpdateRequest) {
emit sampleReady();
return true;
} else {
return QObject::event(event);
}
}

View File

@@ -0,0 +1,117 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DIRECTSHOWSAMPLESCHEDULER_H
#define DIRECTSHOWSAMPLESCHEDULER_H
#include <QtCore/qmutex.h>
#include <QtCore/qobject.h>
#include <QtCore/qsemaphore.h>
#include <dshow.h>
class DirectShowTimedSample;
class DirectShowSampleScheduler : public QObject, public IMemInputPin
{
Q_OBJECT
public:
enum State
{
Stopped = 0x00,
Running = 0x01,
Paused = 0x02,
RunMask = 0x03,
Flushing = 0x04
};
DirectShowSampleScheduler(IUnknown *pin, QObject *parent = 0);
~DirectShowSampleScheduler();
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
// IMemInputPin
HRESULT STDMETHODCALLTYPE GetAllocator(IMemAllocator **ppAllocator);
HRESULT STDMETHODCALLTYPE NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly);
HRESULT STDMETHODCALLTYPE GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps);
HRESULT STDMETHODCALLTYPE Receive(IMediaSample *pSample);
HRESULT STDMETHODCALLTYPE ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed);
HRESULT STDMETHODCALLTYPE ReceiveCanBlock();
void run(REFERENCE_TIME startTime);
void pause();
void stop();
void setFlushing(bool flushing);
IReferenceClock *clock() const { return m_clock; }
void setClock(IReferenceClock *clock);
bool schedule(IMediaSample *sample);
bool scheduleEndOfStream();
IMediaSample *takeSample(bool *eos);
bool event(QEvent *event);
Q_SIGNALS:
void sampleReady();
private:
IUnknown *m_pin;
IReferenceClock *m_clock;
IMemAllocator *m_allocator;
DirectShowTimedSample *m_head;
DirectShowTimedSample *m_tail;
int m_maximumSamples;
int m_state;
REFERENCE_TIME m_startTime;
HANDLE m_timeoutEvent;
HANDLE m_flushEvent;
QSemaphore m_semaphore;
QMutex m_mutex;
};
#endif

View File

@@ -0,0 +1,86 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "directshowvideorenderercontrol.h"
#include "videosurfacefilter.h"
DirectShowVideoRendererControl::DirectShowVideoRendererControl(DirectShowEventLoop *loop, QObject *parent)
: QVideoRendererControl(parent)
, m_loop(loop)
, m_surface(0)
, m_filter(0)
{
}
DirectShowVideoRendererControl::~DirectShowVideoRendererControl()
{
delete m_filter;
}
QAbstractVideoSurface *DirectShowVideoRendererControl::surface() const
{
return m_surface;
}
void DirectShowVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
{
if (surface != m_surface) {
m_surface = surface;
VideoSurfaceFilter *existingFilter = m_filter;
if (surface) {
m_filter = new VideoSurfaceFilter(surface, m_loop);
} else {
m_filter = 0;
}
emit filterChanged();
delete existingFilter;
}
}
IBaseFilter *DirectShowVideoRendererControl::filter()
{
return m_filter;
}

View File

@@ -0,0 +1,75 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef DIRECTSHOWVIDEORENDERERCONTROL_H
#define DIRECTSHOWVIDEORENDERERCONTROL_H
#include "qvideorenderercontrol.h"
#include <dshow.h>
class DirectShowEventLoop;
class VideoSurfaceFilter;
QT_USE_NAMESPACE
class DirectShowVideoRendererControl : public QVideoRendererControl
{
Q_OBJECT
public:
DirectShowVideoRendererControl(DirectShowEventLoop *loop, QObject *parent = 0);
~DirectShowVideoRendererControl();
QAbstractVideoSurface *surface() const;
void setSurface(QAbstractVideoSurface *surface);
IBaseFilter *filter();
Q_SIGNALS:
void filterChanged();
private:
DirectShowEventLoop *m_loop;
QAbstractVideoSurface *m_surface;
VideoSurfaceFilter *m_filter;
};
#endif

View File

@@ -0,0 +1,86 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "mediasamplevideobuffer.h"
MediaSampleVideoBuffer::MediaSampleVideoBuffer(IMediaSample *sample, int bytesPerLine)
: QAbstractVideoBuffer(NoHandle)
, m_sample(sample)
, m_bytesPerLine(bytesPerLine)
, m_mapMode(NotMapped)
{
m_sample->AddRef();
}
MediaSampleVideoBuffer::~MediaSampleVideoBuffer()
{
m_sample->Release();
}
uchar *MediaSampleVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine)
{
if (m_mapMode == NotMapped && mode != NotMapped) {
if (numBytes)
*numBytes = m_sample->GetActualDataLength();
if (bytesPerLine)
*bytesPerLine = m_bytesPerLine;
BYTE *bytes = 0;
if (m_sample->GetPointer(&bytes) == S_OK) {
m_mapMode = mode;
return reinterpret_cast<uchar *>(bytes);
}
}
return 0;
}
void MediaSampleVideoBuffer::unmap()
{
m_mapMode = NotMapped;
}
QAbstractVideoBuffer::MapMode MediaSampleVideoBuffer::mapMode() const
{
return m_mapMode;
}

View File

@@ -0,0 +1,69 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef MEDIASAMPLEVIDEOBUFFER_H
#define MEDIASAMPLEVIDEOBUFFER_H
#include <qabstractvideobuffer.h>
#include <dshow.h>
class MediaSampleVideoBuffer : public QAbstractVideoBuffer
{
public:
MediaSampleVideoBuffer(IMediaSample *sample, int bytesPerLine);
~MediaSampleVideoBuffer();
IMediaSample *sample() { return m_sample; }
uchar *map(MapMode mode, int *numBytes, int *bytesPerLine);
void unmap();
MapMode mapMode() const;
private:
IMediaSample *m_sample;
int m_bytesPerLine;
MapMode m_mapMode;
};
#endif

View File

@@ -0,0 +1,47 @@
INCLUDEPATH += $$PWD
DEFINES += QMEDIA_DIRECTSHOW_PLAYER
HEADERS += \
$$PWD/directshowaudioendpointcontrol.h \
$$PWD/directshoweventloop.h \
$$PWD/directshowglobal.h \
$$PWD/directshowioreader.h \
$$PWD/directshowiosource.h \
$$PWD/directshowmediatype.h \
$$PWD/directshowmediatypelist.h \
$$PWD/directshowmetadatacontrol.h \
$$PWD/directshowpinenum.h \
$$PWD/directshowplayercontrol.h \
$$PWD/directshowplayerservice.h \
$$PWD/directshowsamplescheduler.h \
$$PWD/directshowvideorenderercontrol.h \
$$PWD/mediasamplevideobuffer.h \
$$PWD/videosurfacefilter.h
SOURCES += \
$$PWD/directshowaudioendpointcontrol.cpp \
$$PWD/directshoweventloop.cpp \
$$PWD/directshowioreader.cpp \
$$PWD/directshowiosource.cpp \
$$PWD/directshowmediatype.cpp \
$$PWD/directshowmediatypelist.cpp \
$$PWD/directshowmetadatacontrol.cpp \
$$PWD/directshowpinenum.cpp \
$$PWD/directshowplayercontrol.cpp \
$$PWD/directshowplayerservice.cpp \
$$PWD/directshowsamplescheduler.cpp \
$$PWD/directshowvideorenderercontrol.cpp \
$$PWD/mediasamplevideobuffer.cpp \
$$PWD/videosurfacefilter.cpp
!simulator {
HEADERS += \
$$PWD/vmr9videowindowcontrol.h
SOURCES += \
$$PWD/vmr9videowindowcontrol.cpp
}
LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32 -lgdi32

View File

@@ -0,0 +1,631 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "videosurfacefilter.h"
#include "directshoweventloop.h"
#include "directshowglobal.h"
#include "directshowpinenum.h"
#include "mediasamplevideobuffer.h"
#include <QtCore/qcoreapplication.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qthread.h>
#include <qabstractvideosurface.h>
#include <initguid.h>
// { e23cad72-153d-406c-bf3f-4c4b523d96f2 }
DEFINE_GUID(CLSID_VideoSurfaceFilter,
0xe23cad72, 0x153d, 0x406c, 0xbf, 0x3f, 0x4c, 0x4b, 0x52, 0x3d, 0x96, 0xf2);
VideoSurfaceFilter::VideoSurfaceFilter(
QAbstractVideoSurface *surface, DirectShowEventLoop *loop, QObject *parent)
: QObject(parent)
, m_ref(1)
, m_state(State_Stopped)
, m_surface(surface)
, m_loop(loop)
, m_graph(0)
, m_peerPin(0)
, m_bytesPerLine(0)
, m_startResult(S_OK)
, m_pinId(QString::fromLatin1("reference"))
, m_sampleScheduler(static_cast<IPin *>(this))
{
connect(surface, SIGNAL(supportedFormatsChanged()), this, SLOT(supportedFormatsChanged()));
connect(&m_sampleScheduler, SIGNAL(sampleReady()), this, SLOT(sampleReady()));
}
VideoSurfaceFilter::~VideoSurfaceFilter()
{
Q_ASSERT(m_ref == 1);
}
HRESULT VideoSurfaceFilter::QueryInterface(REFIID riid, void **ppvObject)
{
// 2dd74950-a890-11d1-abe8-00a0c905f375
static const GUID iid_IAmFilterMiscFlags = {
0x2dd74950, 0xa890, 0x11d1, {0xab, 0xe8, 0x00, 0xa0, 0xc9, 0x05, 0xf3, 0x75} };
if (!ppvObject) {
return E_POINTER;
} else if (riid == IID_IUnknown
|| riid == IID_IPersist
|| riid == IID_IMediaFilter
|| riid == IID_IBaseFilter) {
*ppvObject = static_cast<IBaseFilter *>(this);
} else if (riid == iid_IAmFilterMiscFlags) {
*ppvObject = static_cast<IAMFilterMiscFlags *>(this);
} else if (riid == IID_IPin) {
*ppvObject = static_cast<IPin *>(this);
} else if (riid == IID_IMemInputPin) {
*ppvObject = static_cast<IMemInputPin *>(&m_sampleScheduler);
} else {
*ppvObject = 0;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
ULONG VideoSurfaceFilter::AddRef()
{
return InterlockedIncrement(&m_ref);
}
ULONG VideoSurfaceFilter::Release()
{
ULONG ref = InterlockedDecrement(&m_ref);
Q_ASSERT(ref != 0);
return ref;
}
HRESULT VideoSurfaceFilter::GetClassID(CLSID *pClassID)
{
*pClassID = CLSID_VideoSurfaceFilter;
return S_OK;
}
HRESULT VideoSurfaceFilter::Run(REFERENCE_TIME tStart)
{
m_state = State_Running;
m_sampleScheduler.run(tStart);
return S_OK;
}
HRESULT VideoSurfaceFilter::Pause()
{
m_state = State_Paused;
m_sampleScheduler.pause();
return S_OK;
}
HRESULT VideoSurfaceFilter::Stop()
{
m_state = State_Stopped;
m_sampleScheduler.stop();
return S_OK;
}
HRESULT VideoSurfaceFilter::GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
{
if (!pState)
return E_POINTER;
*pState = m_state;
return S_OK;
}
HRESULT VideoSurfaceFilter::SetSyncSource(IReferenceClock *pClock)
{
m_sampleScheduler.setClock(pClock);
return S_OK;
}
HRESULT VideoSurfaceFilter::GetSyncSource(IReferenceClock **ppClock)
{
if (!ppClock) {
return E_POINTER;
} else {
*ppClock = m_sampleScheduler.clock();
if (*ppClock) {
(*ppClock)->AddRef();
return S_OK;
} else {
return S_FALSE;
}
}
}
HRESULT VideoSurfaceFilter::EnumPins(IEnumPins **ppEnum)
{
if (ppEnum) {
*ppEnum = new DirectShowPinEnum(QList<IPin *>() << this);
return S_OK;
} else {
return E_POINTER;
}
}
HRESULT VideoSurfaceFilter::FindPin(LPCWSTR pId, IPin **ppPin)
{
if (!ppPin || !pId) {
return E_POINTER;
} else if (QString::fromWCharArray(pId) == m_pinId) {
AddRef();
*ppPin = this;
return S_OK;
} else {
return VFW_E_NOT_FOUND;
}
}
HRESULT VideoSurfaceFilter::JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName)
{
m_graph = pGraph;
m_name = QString::fromWCharArray(pName);
return S_OK;
}
HRESULT VideoSurfaceFilter::QueryFilterInfo(FILTER_INFO *pInfo)
{
if (pInfo) {
QString name = m_name;
if (name.length() >= MAX_FILTER_NAME)
name.truncate(MAX_FILTER_NAME - 1);
int length = name.toWCharArray(pInfo->achName);
pInfo->achName[length] = '\0';
if (m_graph)
m_graph->AddRef();
pInfo->pGraph = m_graph;
return S_OK;
} else {
return E_POINTER;
}
}
HRESULT VideoSurfaceFilter::QueryVendorInfo(LPWSTR *pVendorInfo)
{
Q_UNUSED(pVendorInfo);
return E_NOTIMPL;
}
ULONG VideoSurfaceFilter::GetMiscFlags()
{
return AM_FILTER_MISC_FLAGS_IS_RENDERER;
}
HRESULT VideoSurfaceFilter::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
{
// This is an input pin, you shouldn't be calling Connect on it.
return E_POINTER;
}
HRESULT VideoSurfaceFilter::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
{
if (!pConnector) {
return E_POINTER;
} else if (!pmt) {
return E_POINTER;
} else {
HRESULT hr;
QMutexLocker locker(&m_mutex);
if (m_peerPin) {
hr = VFW_E_ALREADY_CONNECTED;
} else if (pmt->majortype != MEDIATYPE_Video) {
hr = VFW_E_TYPE_NOT_ACCEPTED;
} else {
m_surfaceFormat = DirectShowMediaType::formatFromType(*pmt);
m_bytesPerLine = DirectShowMediaType::bytesPerLine(m_surfaceFormat);
if (thread() == QThread::currentThread()) {
hr = start();
} else {
m_loop->postEvent(this, new QEvent(QEvent::Type(StartSurface)));
m_wait.wait(&m_mutex);
hr = m_startResult;
}
}
if (hr == S_OK) {
m_peerPin = pConnector;
m_peerPin->AddRef();
DirectShowMediaType::copy(&m_mediaType, *pmt);
}
return hr;
}
}
HRESULT VideoSurfaceFilter::start()
{
if (!m_surface->isFormatSupported(m_surfaceFormat)) {
return VFW_E_TYPE_NOT_ACCEPTED;
}
if (!m_surface->start(m_surfaceFormat)) {
return VFW_E_TYPE_NOT_ACCEPTED;
} else {
return S_OK;
}
}
HRESULT VideoSurfaceFilter::Disconnect()
{
QMutexLocker locker(&m_mutex);
if (!m_peerPin)
return S_FALSE;
if (thread() == QThread::currentThread()) {
stop();
} else {
m_loop->postEvent(this, new QEvent(QEvent::Type(StopSurface)));
m_wait.wait(&m_mutex);
}
m_mediaType.clear();
m_sampleScheduler.NotifyAllocator(0, FALSE);
m_peerPin->Release();
m_peerPin = 0;
return S_OK;
}
void VideoSurfaceFilter::stop()
{
m_surface->stop();
}
HRESULT VideoSurfaceFilter::ConnectedTo(IPin **ppPin)
{
if (!ppPin) {
return E_POINTER;
} else {
QMutexLocker locker(&m_mutex);
if (!m_peerPin) {
return VFW_E_NOT_CONNECTED;
} else {
m_peerPin->AddRef();
*ppPin = m_peerPin;
return S_OK;
}
}
}
HRESULT VideoSurfaceFilter::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
{
if (!pmt) {
return E_POINTER;
} else {
QMutexLocker locker(&m_mutex);
if (!m_peerPin) {
return VFW_E_NOT_CONNECTED;
} else {
DirectShowMediaType::copy(pmt, m_mediaType);
return S_OK;
}
}
}
HRESULT VideoSurfaceFilter::QueryPinInfo(PIN_INFO *pInfo)
{
if (!pInfo) {
return E_POINTER;
} else {
AddRef();
pInfo->pFilter = this;
pInfo->dir = PINDIR_INPUT;
const int bytes = qMin(MAX_FILTER_NAME, (m_pinId.length() + 1) * 2);
qMemCopy(pInfo->achName, m_pinId.utf16(), bytes);
return S_OK;
}
}
HRESULT VideoSurfaceFilter::QueryId(LPWSTR *Id)
{
if (!Id) {
return E_POINTER;
} else {
const int bytes = (m_pinId.length() + 1) * 2;
*Id = static_cast<LPWSTR>(::CoTaskMemAlloc(bytes));
qMemCopy(*Id, m_pinId.utf16(), bytes);
return S_OK;
}
}
HRESULT VideoSurfaceFilter::QueryAccept(const AM_MEDIA_TYPE *pmt)
{
return !m_surface->isFormatSupported(DirectShowMediaType::formatFromType(*pmt))
? S_OK
: S_FALSE;
}
HRESULT VideoSurfaceFilter::EnumMediaTypes(IEnumMediaTypes **ppEnum)
{
if (!ppEnum) {
return E_POINTER;
} else {
QMutexLocker locker(&m_mutex);
*ppEnum = createMediaTypeEnum();
return S_OK;
}
}
HRESULT VideoSurfaceFilter::QueryInternalConnections(IPin **apPin, ULONG *nPin)
{
Q_UNUSED(apPin);
Q_UNUSED(nPin);
return E_NOTIMPL;
}
HRESULT VideoSurfaceFilter::EndOfStream()
{
QMutexLocker locker(&m_mutex);
if (!m_sampleScheduler.scheduleEndOfStream()) {
if (IMediaEventSink *sink = com_cast<IMediaEventSink>(m_graph, IID_IMediaEventSink)) {
sink->Notify(
EC_COMPLETE,
S_OK,
reinterpret_cast<LONG_PTR>(static_cast<IBaseFilter *>(this)));
sink->Release();
}
}
return S_OK;
}
HRESULT VideoSurfaceFilter::BeginFlush()
{
QMutexLocker locker(&m_mutex);
m_sampleScheduler.setFlushing(true);
if (thread() == QThread::currentThread()) {
flush();
} else {
m_loop->postEvent(this, new QEvent(QEvent::Type(FlushSurface)));
m_wait.wait(&m_mutex);
}
return S_OK;
}
HRESULT VideoSurfaceFilter::EndFlush()
{
QMutexLocker locker(&m_mutex);
m_sampleScheduler.setFlushing(false);
return S_OK;
}
void VideoSurfaceFilter::flush()
{
m_surface->present(QVideoFrame());
m_wait.wakeAll();
}
HRESULT VideoSurfaceFilter::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
{
Q_UNUSED(tStart);
Q_UNUSED(tStop);
Q_UNUSED(dRate);
return S_OK;
}
HRESULT VideoSurfaceFilter::QueryDirection(PIN_DIRECTION *pPinDir)
{
if (!pPinDir) {
return E_POINTER;
} else {
*pPinDir = PINDIR_INPUT;
return S_OK;
}
}
int VideoSurfaceFilter::currentMediaTypeToken()
{
QMutexLocker locker(&m_mutex);
return DirectShowMediaTypeList::currentMediaTypeToken();
}
HRESULT VideoSurfaceFilter::nextMediaType(
int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount)
{
QMutexLocker locker(&m_mutex);
return DirectShowMediaTypeList::nextMediaType(token, index, count, types, fetchedCount);
}
HRESULT VideoSurfaceFilter::skipMediaType(int token, int *index, ULONG count)
{
QMutexLocker locker(&m_mutex);
return DirectShowMediaTypeList::skipMediaType(token, index, count);
}
HRESULT VideoSurfaceFilter::cloneMediaType(int token, int index, IEnumMediaTypes **enumeration)
{
QMutexLocker locker(&m_mutex);
return DirectShowMediaTypeList::cloneMediaType(token, index, enumeration);
}
void VideoSurfaceFilter::customEvent(QEvent *event)
{
if (event->type() == StartSurface) {
QMutexLocker locker(&m_mutex);
m_startResult = start();
m_wait.wakeAll();
} else if (event->type() == StopSurface) {
QMutexLocker locker(&m_mutex);
stop();
m_wait.wakeAll();
} else if (event->type() == FlushSurface) {
QMutexLocker locker(&m_mutex);
flush();
m_wait.wakeAll();
} else {
QObject::customEvent(event);
}
}
void VideoSurfaceFilter::supportedFormatsChanged()
{
QMutexLocker locker(&m_mutex);
// MEDIASUBTYPE_None;
static const GUID none = {
0xe436eb8e, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70} };
QList<QVideoFrame::PixelFormat> formats = m_surface->supportedPixelFormats();
QVector<AM_MEDIA_TYPE> mediaTypes;
mediaTypes.reserve(formats.count());
AM_MEDIA_TYPE type;
type.majortype = MEDIATYPE_Video;
type.bFixedSizeSamples = TRUE;
type.bTemporalCompression = FALSE;
type.lSampleSize = 0;
type.formattype = GUID_NULL;
type.pUnk = 0;
type.cbFormat = 0;
type.pbFormat = 0;
foreach (QVideoFrame::PixelFormat format, formats) {
type.subtype = DirectShowMediaType::convertPixelFormat(format);
if (type.subtype != none)
mediaTypes.append(type);
}
setMediaTypes(mediaTypes);
}
void VideoSurfaceFilter::sampleReady()
{
bool eos = false;
IMediaSample *sample = m_sampleScheduler.takeSample(&eos);
if (sample) {
m_surface->present(QVideoFrame(
new MediaSampleVideoBuffer(sample, m_bytesPerLine),
m_surfaceFormat.frameSize(),
m_surfaceFormat.pixelFormat()));
sample->Release();
if (eos) {
if (IMediaEventSink *sink = com_cast<IMediaEventSink>(m_graph, IID_IMediaEventSink)) {
sink->Notify(
EC_COMPLETE,
S_OK,
reinterpret_cast<LONG_PTR>(static_cast<IBaseFilter *>(this)));
sink->Release();
}
}
}
}

View File

@@ -0,0 +1,176 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef VIDEOSURFACEFILTER_H
#define VIDEOSURFACEFILTER_H
#include "directshowglobal.h"
#include "directshowmediatypelist.h"
#include "directshowsamplescheduler.h"
#include "directshowmediatype.h"
#include <QtCore/qbasictimer.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qmutex.h>
#include <QtCore/qsemaphore.h>
#include <QtCore/qstring.h>
#include <QtCore/qwaitcondition.h>
#include <dshow.h>
QT_BEGIN_NAMESPACE
class QAbstractVideoSurface;
QT_END_NAMESPACE
class DirectShowEventLoop;
class VideoSurfaceFilter
: public QObject
, public DirectShowMediaTypeList
, public IBaseFilter
, public IAMFilterMiscFlags
, public IPin
{
Q_OBJECT
public:
VideoSurfaceFilter(
QAbstractVideoSurface *surface, DirectShowEventLoop *loop, QObject *parent = 0);
~VideoSurfaceFilter();
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
// IPersist
HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
// IMediaFilter
HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart);
HRESULT STDMETHODCALLTYPE Pause();
HRESULT STDMETHODCALLTYPE Stop();
HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState);
HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock);
HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **ppClock);
// IBaseFilter
HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **ppEnum);
HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin **ppPin);
HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName);
HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *pInfo);
HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *pVendorInfo);
// IAMFilterMiscFlags
ULONG STDMETHODCALLTYPE GetMiscFlags();
// IPin
HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE Disconnect();
HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **ppPin);
HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo);
HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id);
HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum);
HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin);
HRESULT STDMETHODCALLTYPE EndOfStream();
HRESULT STDMETHODCALLTYPE BeginFlush();
HRESULT STDMETHODCALLTYPE EndFlush();
HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir);
int currentMediaTypeToken();
HRESULT nextMediaType(
int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount);
HRESULT skipMediaType(int token, int *index, ULONG count);
HRESULT cloneMediaType(int token, int index, IEnumMediaTypes **enumeration);
protected:
void customEvent(QEvent *event);
private Q_SLOTS:
void supportedFormatsChanged();
void sampleReady();
private:
HRESULT start();
void stop();
void flush();
enum
{
StartSurface = QEvent::User,
StopSurface,
FlushSurface
};
LONG m_ref;
FILTER_STATE m_state;
QAbstractVideoSurface *m_surface;
DirectShowEventLoop *m_loop;
IFilterGraph *m_graph;
IPin *m_peerPin;
int m_bytesPerLine;
HRESULT m_startResult;
QString m_name;
QString m_pinId;
DirectShowMediaType m_mediaType;
QVideoSurfaceFormat m_surfaceFormat;
QMutex m_mutex;
QWaitCondition m_wait;
DirectShowSampleScheduler m_sampleScheduler;
};
#endif

View File

@@ -0,0 +1,329 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "vmr9videowindowcontrol.h"
#include "directshowglobal.h"
Vmr9VideoWindowControl::Vmr9VideoWindowControl(QObject *parent)
: QVideoWindowControl(parent)
, m_filter(com_new<IBaseFilter>(CLSID_VideoMixingRenderer9, IID_IBaseFilter))
, m_windowId(0)
, m_dirtyValues(0)
, m_aspectRatioMode(Qt::KeepAspectRatio)
, m_brightness(0)
, m_contrast(0)
, m_hue(0)
, m_saturation(0)
, m_fullScreen(false)
{
if (IVMRFilterConfig9 *config = com_cast<IVMRFilterConfig9>(m_filter, IID_IVMRFilterConfig9)) {
config->SetRenderingMode(VMR9Mode_Windowless);
config->SetNumberOfStreams(1);
config->Release();
}
}
Vmr9VideoWindowControl::~Vmr9VideoWindowControl()
{
if (m_filter)
m_filter->Release();
}
WId Vmr9VideoWindowControl::winId() const
{
return m_windowId;
}
void Vmr9VideoWindowControl::setWinId(WId id)
{
m_windowId = id;
if (QWidget *widget = QWidget::find(m_windowId)) {
const QColor color = widget->palette().color(QPalette::Window);
m_windowColor = RGB(color.red(), color.green(), color.blue());
}
if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>(
m_filter, IID_IVMRWindowlessControl9)) {
control->SetVideoClippingWindow(m_windowId);
control->SetBorderColor(m_windowColor);
control->Release();
}
}
QRect Vmr9VideoWindowControl::displayRect() const
{
return m_displayRect;
}
void Vmr9VideoWindowControl::setDisplayRect(const QRect &rect)
{
m_displayRect = rect;
if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>(
m_filter, IID_IVMRWindowlessControl9)) {
RECT sourceRect = { 0, 0, 0, 0 };
RECT displayRect = { rect.left(), rect.top(), rect.right() + 1, rect.bottom() + 1 };
control->GetNativeVideoSize(&sourceRect.right, &sourceRect.bottom, 0, 0);
if (m_aspectRatioMode == Qt::KeepAspectRatioByExpanding) {
QSize clippedSize = rect.size();
clippedSize.scale(sourceRect.right, sourceRect.bottom, Qt::KeepAspectRatio);
sourceRect.left = (sourceRect.right - clippedSize.width()) / 2;
sourceRect.top = (sourceRect.bottom - clippedSize.height()) / 2;
sourceRect.right = sourceRect.left + clippedSize.width();
sourceRect.bottom = sourceRect.top + clippedSize.height();
}
control->SetVideoPosition(&sourceRect, &displayRect);
control->Release();
}
}
bool Vmr9VideoWindowControl::isFullScreen() const
{
return m_fullScreen;
}
void Vmr9VideoWindowControl::setFullScreen(bool fullScreen)
{
emit fullScreenChanged(m_fullScreen = fullScreen);
}
void Vmr9VideoWindowControl::repaint()
{
PAINTSTRUCT paint;
if (HDC dc = ::BeginPaint(m_windowId, &paint)) {
HRESULT hr = E_FAIL;
if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>(
m_filter, IID_IVMRWindowlessControl9)) {
hr = control->RepaintVideo(m_windowId, dc);
control->Release();
}
if (!SUCCEEDED(hr)) {
HPEN pen = ::CreatePen(PS_SOLID, 1, m_windowColor);
HBRUSH brush = ::CreateSolidBrush(m_windowColor);
::SelectObject(dc, pen);
::SelectObject(dc, brush);
::Rectangle(
dc,
m_displayRect.left(),
m_displayRect.top(),
m_displayRect.right() + 1,
m_displayRect.bottom() + 1);
::DeleteObject(pen);
::DeleteObject(brush);
}
::EndPaint(m_windowId, &paint);
}
}
QSize Vmr9VideoWindowControl::nativeSize() const
{
QSize size;
if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>(
m_filter, IID_IVMRWindowlessControl9)) {
LONG width;
LONG height;
if (control->GetNativeVideoSize(&width, &height, 0, 0) == S_OK)
size = QSize(width, height);
control->Release();
}
return size;
}
Qt::AspectRatioMode Vmr9VideoWindowControl::aspectRatioMode() const
{
return m_aspectRatioMode;
}
void Vmr9VideoWindowControl::setAspectRatioMode(Qt::AspectRatioMode mode)
{
m_aspectRatioMode = mode;
if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>(
m_filter, IID_IVMRWindowlessControl9)) {
switch (mode) {
case Qt::IgnoreAspectRatio:
control->SetAspectRatioMode(VMR9ARMode_None);
break;
case Qt::KeepAspectRatio:
control->SetAspectRatioMode(VMR9ARMode_LetterBox);
break;
case Qt::KeepAspectRatioByExpanding:
control->SetAspectRatioMode(VMR9ARMode_LetterBox);
setDisplayRect(m_displayRect);
break;
default:
break;
}
control->Release();
}
}
int Vmr9VideoWindowControl::brightness() const
{
return m_brightness;
}
void Vmr9VideoWindowControl::setBrightness(int brightness)
{
m_brightness = brightness;
m_dirtyValues |= ProcAmpControl9_Brightness;
setProcAmpValues();
emit brightnessChanged(brightness);
}
int Vmr9VideoWindowControl::contrast() const
{
return m_contrast;
}
void Vmr9VideoWindowControl::setContrast(int contrast)
{
m_contrast = contrast;
m_dirtyValues |= ProcAmpControl9_Contrast;
setProcAmpValues();
emit contrastChanged(contrast);
}
int Vmr9VideoWindowControl::hue() const
{
return m_hue;
}
void Vmr9VideoWindowControl::setHue(int hue)
{
m_hue = hue;
m_dirtyValues |= ProcAmpControl9_Hue;
setProcAmpValues();
emit hueChanged(hue);
}
int Vmr9VideoWindowControl::saturation() const
{
return m_saturation;
}
void Vmr9VideoWindowControl::setSaturation(int saturation)
{
m_saturation = saturation;
m_dirtyValues |= ProcAmpControl9_Saturation;
setProcAmpValues();
emit saturationChanged(saturation);
}
void Vmr9VideoWindowControl::setProcAmpValues()
{
if (IVMRMixerControl9 *control = com_cast<IVMRMixerControl9>(m_filter, IID_IVMRMixerControl9)) {
VMR9ProcAmpControl procAmp;
procAmp.dwSize = sizeof(VMR9ProcAmpControl);
procAmp.dwFlags = m_dirtyValues;
if (m_dirtyValues & ProcAmpControl9_Brightness) {
procAmp.Brightness = scaleProcAmpValue(
control, ProcAmpControl9_Brightness, m_brightness);
}
if (m_dirtyValues & ProcAmpControl9_Contrast) {
procAmp.Contrast = scaleProcAmpValue(
control, ProcAmpControl9_Contrast, m_contrast);
}
if (m_dirtyValues & ProcAmpControl9_Hue) {
procAmp.Hue = scaleProcAmpValue(
control, ProcAmpControl9_Hue, m_hue);
}
if (m_dirtyValues & ProcAmpControl9_Saturation) {
procAmp.Saturation = scaleProcAmpValue(
control, ProcAmpControl9_Saturation, m_saturation);
}
if (SUCCEEDED(control->SetProcAmpControl(0, &procAmp))) {
m_dirtyValues = 0;
}
control->Release();
}
}
float Vmr9VideoWindowControl::scaleProcAmpValue(
IVMRMixerControl9 *control, VMR9ProcAmpControlFlags property, int value) const
{
float scaledValue = 0.0;
VMR9ProcAmpControlRange range;
range.dwSize = sizeof(VMR9ProcAmpControlRange);
range.dwProperty = property;
if (SUCCEEDED(control->GetProcAmpControlRange(0, &range))) {
scaledValue = range.DefaultValue;
if (value > 0)
scaledValue += float(value) * (range.MaxValue - range.DefaultValue) / 100;
else if (value < 0)
scaledValue -= float(value) * (range.MinValue - range.DefaultValue) / 100;
}
return scaledValue;
}

View File

@@ -0,0 +1,108 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef VMR9VIDEOWINDOWCONTROL_H
#define VMR9VIDEOWINDOWCONTROL_H
#include "qvideowindowcontrol.h"
#include <dshow.h>
#include <d3d9.h>
#include <vmr9.h>
QT_USE_NAMESPACE
class Vmr9VideoWindowControl : public QVideoWindowControl
{
Q_OBJECT
public:
Vmr9VideoWindowControl(QObject *parent = 0);
~Vmr9VideoWindowControl();
IBaseFilter *filter() const { return m_filter; }
WId winId() const;
void setWinId(WId id);
QRect displayRect() const;
void setDisplayRect(const QRect &rect);
bool isFullScreen() const;
void setFullScreen(bool fullScreen);
void repaint();
QSize nativeSize() const;
Qt::AspectRatioMode aspectRatioMode() const;
void setAspectRatioMode(Qt::AspectRatioMode mode);
int brightness() const;
void setBrightness(int brightness);
int contrast() const;
void setContrast(int contrast);
int hue() const;
void setHue(int hue);
int saturation() const;
void setSaturation(int saturation);
private:
void setProcAmpValues();
float scaleProcAmpValue(
IVMRMixerControl9 *control, VMR9ProcAmpControlFlags property, int value) const;
IBaseFilter *m_filter;
WId m_windowId;
COLORREF m_windowColor;
DWORD m_dirtyValues;
Qt::AspectRatioMode m_aspectRatioMode;
QRect m_displayRect;
int m_brightness;
int m_contrast;
int m_hue;
int m_saturation;
bool m_fullScreen;
};
#endif