]> Some of my projects - aniplayer2.git/commitdiff
Aniplayer2, Qt5, no phonon
authorAPTX <marek321@gmail.com>
Thu, 14 Feb 2013 13:27:40 +0000 (14:27 +0100)
committerAPTX <marek321@gmail.com>
Thu, 14 Feb 2013 13:27:40 +0000 (14:27 +0100)
24 files changed:
.gitignore [new file with mode: 0644]
aniplayer2.pro [new file with mode: 0644]
aniplayer2/aniplayer.cpp [new file with mode: 0644]
aniplayer2/aniplayer.h [new file with mode: 0644]
aniplayer2/aniplayer2.pri [new file with mode: 0644]
aniplayer2/aniplayer2.pro [new file with mode: 0644]
aniplayer2/aniplayer2_global.h [new file with mode: 0644]
aniplayer2/videowidget.cpp [new file with mode: 0644]
aniplayer2/videowidget.h [new file with mode: 0644]
aniplayer2_dshow/aniplayer2_dshow.pri [new file with mode: 0644]
aniplayer2_dshow/aniplayer2_dshow.pro [new file with mode: 0644]
aniplayer2_dshow/aniplayer2_dshow_global.h [new file with mode: 0644]
aniplayer2_dshow/aniplayerdshow.cpp [new file with mode: 0644]
aniplayer2_dshow/aniplayerdshow.h [new file with mode: 0644]
aniplayer2_dshow/aniplayerdshowinternal.cpp [new file with mode: 0644]
aniplayer2_dshow/aniplayerdshowinternal.h [new file with mode: 0644]
aniplayer2_dshow/videowidgetdshow.cpp [new file with mode: 0644]
aniplayer2_dshow/videowidgetdshow.h [new file with mode: 0644]
config.pri [new file with mode: 0644]
player/main.cpp [new file with mode: 0644]
player/mainwindow.cpp [new file with mode: 0644]
player/mainwindow.h [new file with mode: 0644]
player/mainwindow.ui [new file with mode: 0644]
player/player.pro [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..2f6642b
--- /dev/null
@@ -0,0 +1,76 @@
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+.qmake.cache
+tags
+.DS_Store
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+
+# qtcreator generated files
+*.pro.user
+*.pro.user.*
+*.autosave
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.exp
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Directories to ignore
+# ---------------------
+
+build
+debug
+release
+lib/qtsingleapplication/lib
+lib/qtsingleapplication/examples
+lib/qtsingleapplication/doc
+.tmp
+qtc-gdbmacros
+
+# Binaries
+# --------
+build/*.dll
+build/*.lib
+build/*.exe
+build/*.so*
+
+
diff --git a/aniplayer2.pro b/aniplayer2.pro
new file mode 100644 (file)
index 0000000..83c1f96
--- /dev/null
@@ -0,0 +1,8 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+
+include(config.pri)
+
+SUBDIRS += aniplayer2
+win32: SUBDIRS += aniplayer2_dshow
+SUBDIRS += player
diff --git a/aniplayer2/aniplayer.cpp b/aniplayer2/aniplayer.cpp
new file mode 100644 (file)
index 0000000..4937394
--- /dev/null
@@ -0,0 +1,43 @@
+#include "aniplayer.h"
+
+
+AniPlayer::AniPlayer(QObject *parent) : QObject(parent), m_state(Stopped)
+{
+}
+
+AniPlayer::~AniPlayer()
+{
+}
+
+AniPlayer::State AniPlayer::state() const
+{
+       return m_state;
+}
+
+void AniPlayer::open(const QString &file)
+{
+       iopen(file);
+}
+
+void AniPlayer::play()
+{
+       iplay();
+}
+
+void AniPlayer::pause()
+{
+       ipause();
+}
+
+void AniPlayer::stop()
+{
+       istop();
+}
+
+void AniPlayer::togglePause()
+{
+       if (m_state == Paused)
+               play();
+       else
+               pause();
+}
diff --git a/aniplayer2/aniplayer.h b/aniplayer2/aniplayer.h
new file mode 100644 (file)
index 0000000..6601c6d
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef ANIPLAYER_H
+#define ANIPLAYER_H
+
+#include "aniplayer2_global.h"
+
+#include <QObject>
+#include <QString>
+
+class VideoWidget;
+
+class ANIPLAYER2SHARED_EXPORT AniPlayer : public QObject
+{
+       Q_OBJECT
+public:
+       enum State
+       {
+               Stopped,
+               Playing,
+               Paused,
+               Error
+       };
+
+       AniPlayer(QObject *parent = 0);
+       virtual ~AniPlayer();
+
+       virtual VideoWidget *videoWidget() = 0;
+       virtual void widgetChanged() = 0;
+
+       State state() const;
+
+public slots:
+       void open(const QString &file);
+       void play();
+       void pause();
+       void stop();
+
+       void togglePause();
+
+
+protected:
+       virtual void iopen(const QString &file) = 0;
+       virtual void iplay() = 0;
+       virtual void ipause() = 0;
+       virtual void istop() = 0;
+
+       State m_state;
+};
+
+#endif // ANIPLAYER_H
diff --git a/aniplayer2/aniplayer2.pri b/aniplayer2/aniplayer2.pri
new file mode 100644 (file)
index 0000000..7757fbb
--- /dev/null
@@ -0,0 +1,5 @@
+INCLUDEPATH += $$PWD
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+LIBS += -laniplayer2
+LIBS += -L$$PWD/../build
diff --git a/aniplayer2/aniplayer2.pro b/aniplayer2/aniplayer2.pro
new file mode 100644 (file)
index 0000000..05d613e
--- /dev/null
@@ -0,0 +1,25 @@
+QT += core gui
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+TARGET = aniplayer2
+DESTDIR = ../build
+
+TEMPLATE = lib
+
+DEFINES += ANIPLAYER2_LIBRARY
+
+SOURCES += aniplayer.cpp
+
+HEADERS += aniplayer2_global.h \
+       aniplayer.h\
+       videowidget.h
+
+
+HEADERS += \
+
+
+SOURCES += \
+       videowidget.cpp
+
+include(../config.pri)
diff --git a/aniplayer2/aniplayer2_global.h b/aniplayer2/aniplayer2_global.h
new file mode 100644 (file)
index 0000000..c26d14c
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef ANIPLAYER2_GLOBAL_H
+#define ANIPLAYER2_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#if defined(ANIPLAYER2_LIBRARY)
+#  define ANIPLAYER2SHARED_EXPORT Q_DECL_EXPORT
+#else
+#  define ANIPLAYER2SHARED_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // LIBANIPLAYER2_GLOBAL_H
diff --git a/aniplayer2/videowidget.cpp b/aniplayer2/videowidget.cpp
new file mode 100644 (file)
index 0000000..de69e87
--- /dev/null
@@ -0,0 +1,6 @@
+#include "videowidget.h"
+
+VideoWidget::VideoWidget(QWidget *parent) :
+       QWidget(parent)
+{
+}
diff --git a/aniplayer2/videowidget.h b/aniplayer2/videowidget.h
new file mode 100644 (file)
index 0000000..67648ad
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef VIDEOWIDGET_H
+#define VIDEOWIDGET_H
+
+#include "aniplayer2_global.h"
+#include <QWidget>
+
+class ANIPLAYER2SHARED_EXPORT VideoWidget : public QWidget
+{
+       Q_OBJECT
+public:
+       explicit VideoWidget(QWidget *parent = 0);
+
+signals:
+
+public slots:
+
+};
+
+#endif // VIDEOWIDGET_H
diff --git a/aniplayer2_dshow/aniplayer2_dshow.pri b/aniplayer2_dshow/aniplayer2_dshow.pri
new file mode 100644 (file)
index 0000000..6a0e8e5
--- /dev/null
@@ -0,0 +1,5 @@
+INCLUDEPATH += $$PWD
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+LIBS += -laniplayer2_dshow
+LIBS += -L$$PWD/../build
diff --git a/aniplayer2_dshow/aniplayer2_dshow.pro b/aniplayer2_dshow/aniplayer2_dshow.pro
new file mode 100644 (file)
index 0000000..7bef14d
--- /dev/null
@@ -0,0 +1,29 @@
+QT += core gui
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+TARGET = aniplayer2_dshow
+DESTDIR = ../build
+
+TEMPLATE = lib
+
+DEFINES += ANIPLAYER2_DSHOW_LIBRARY
+
+
+HEADERS += aniplayer2_dshow_global.h
+
+HEADERS += \
+       aniplayerdshow.h \
+       aniplayerdshowinternal.h \
+       videowidgetdshow.h
+
+
+SOURCES += \
+       aniplayerdshow.cpp \
+       aniplayerdshowinternal.cpp \
+       videowidgetdshow.cpp
+
+include(../config.pri)
+include(../aniplayer2/aniplayer2.pri)
+
+LIBS += -lstrmiids -lole32
diff --git a/aniplayer2_dshow/aniplayer2_dshow_global.h b/aniplayer2_dshow/aniplayer2_dshow_global.h
new file mode 100644 (file)
index 0000000..b5d8367
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef ANIPLAYER2_DSHOW_GLOBAL_H
+#define ANIPLAYER2_DSHOW_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#if defined(ANIPLAYER2_DSHOW_LIBRARY)
+#  define ANIPLAYER2_DSHOWSHARED_EXPORT Q_DECL_EXPORT
+#else
+#  define ANIPLAYER2_DSHOWSHARED_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // ANIPLAYER2_DSHOW_GLOBAL_H
diff --git a/aniplayer2_dshow/aniplayerdshow.cpp b/aniplayer2_dshow/aniplayerdshow.cpp
new file mode 100644 (file)
index 0000000..63e6f34
--- /dev/null
@@ -0,0 +1,63 @@
+#include "aniplayerdshow.h"
+
+#include "aniplayerdshowinternal.h"
+#include "videowidgetdshow.h"
+
+#include <QDebug>
+
+AniPlayerDShow::AniPlayerDShow(QObject *parent) :
+       AniPlayer(parent)
+{
+       HRESULT hr;
+
+       hr = CoInitialize(NULL);
+       if (FAILED(hr))
+               qDebug() << "Failed to initialize COM";
+
+       m_videoWidget = new VideoWidgetDShow(this);
+       d = new AniPlayerDShowInternal(this);
+}
+
+AniPlayerDShow::~AniPlayerDShow()
+{
+       CoUninitialize();
+}
+
+VideoWidget *AniPlayerDShow::videoWidget()
+{
+       return m_videoWidget;
+}
+
+void AniPlayerDShow::widgetChanged()
+{
+       d->UpdateVideoWindow(0);
+       d->Repaint();
+}
+
+void AniPlayerDShow::iopen(const QString &file)
+{
+       d->OpenFile(reinterpret_cast<const wchar_t *>(file.utf16()));
+}
+
+void AniPlayerDShow::iplay()
+{
+       if (m_state == Paused || m_state == Stopped)
+       if (d->play())
+               m_state = Playing;
+}
+
+void AniPlayerDShow::ipause()
+{
+       if (m_state != Playing)
+               return;
+
+       if (d->pause())
+               m_state = Paused;
+}
+
+void AniPlayerDShow::istop()
+{
+       if (m_state == Playing || m_state == Paused)
+               if (d->stop())
+                       m_state = Stopped;
+}
diff --git a/aniplayer2_dshow/aniplayerdshow.h b/aniplayer2_dshow/aniplayerdshow.h
new file mode 100644 (file)
index 0000000..6b6f4ac
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef ANIPLAYERDSHOW_H
+#define ANIPLAYERDSHOW_H
+
+#include "aniplayer2_dshow_global.h"
+#include <aniplayer.h>
+
+class VideoWidgetDShow;
+
+struct AniPlayerDShowInternal;
+
+class ANIPLAYER2_DSHOWSHARED_EXPORT AniPlayerDShow : public AniPlayer
+{
+       Q_OBJECT
+public:
+       explicit AniPlayerDShow(QObject *parent = 0);
+       ~AniPlayerDShow();
+
+       VideoWidget *videoWidget();
+       void widgetChanged();
+
+
+signals:
+
+protected:
+       void iopen(const QString &file);
+       void iplay();
+       void ipause();
+       void istop();
+
+private:
+       AniPlayerDShowInternal *d;
+
+       VideoWidgetDShow *m_videoWidget;
+};
+
+#endif // ANIPLAYERDSHOW_H
diff --git a/aniplayer2_dshow/aniplayerdshowinternal.cpp b/aniplayer2_dshow/aniplayerdshowinternal.cpp
new file mode 100644 (file)
index 0000000..51fe5cd
--- /dev/null
@@ -0,0 +1,488 @@
+#include "aniplayerdshowinternal.h"
+
+#include "videowidgetdshow.h"
+#include "aniplayerdshow.h"
+
+#include <Dshow.h>
+#include <Evr.h>
+
+HRESULT IsPinConnected(IPin *pPin, BOOL *pResult);
+HRESULT IsPinDirection(IPin *pPin, PIN_DIRECTION dir, BOOL *pResult);
+HRESULT AddFilterByCLSID(IGraphBuilder *pGraph, REFGUID clsid, IBaseFilter **ppF, LPCWSTR wszName);
+HRESULT FindConnectedPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin);
+
+AniPlayerDShowInternal::AniPlayerDShowInternal(AniPlayerDShow *player_) : player(player_)
+{
+       pGraph = 0;
+       pControl = 0;
+       pEvent = 0;
+       pSeeking = 0;
+
+       pEVR = 0;
+       pVideoDisplay = 0;
+}
+
+AniPlayerDShowInternal::~AniPlayerDShowInternal()
+{
+       SafeRelease(&pControl);
+       SafeRelease(&pEvent);
+       SafeRelease(&pGraph);
+       SafeRelease(&pSeeking)
+}
+
+bool AniPlayerDShowInternal::play()
+{
+       HRESULT hr = pControl->Run();
+       return SUCCEEDED(hr);
+}
+
+bool AniPlayerDShowInternal::pause()
+{
+        HRESULT hr = pControl->Pause();
+        return SUCCEEDED(hr);
+}
+
+bool AniPlayerDShowInternal::stop()
+{
+       HRESULT hr = pControl->Stop();
+       return SUCCEEDED(hr);
+}
+
+QSize AniPlayerDShowInternal::videoSize() const
+{
+       if (!pVideoDisplay)
+               return QSize();
+
+       SIZE nativeSize;
+       SIZE aspectRatioSize;
+
+       pVideoDisplay->GetNativeVideoSize(&nativeSize, &aspectRatioSize);
+
+       return QSize(nativeSize.cx, nativeSize.cy);
+}
+
+HRESULT AniPlayerDShowInternal::InitializeGraph()
+{
+       TearDownGraph();
+
+       // Create the Filter Graph Manager.
+       HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL,
+               CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pGraph));
+       if (FAILED(hr))
+       {
+               goto done;
+       }
+
+       hr = pGraph->QueryInterface(IID_PPV_ARGS(&pControl));
+       if (FAILED(hr))
+       {
+               goto done;
+       }
+
+       hr = pGraph->QueryInterface(IID_PPV_ARGS(&pEvent));
+       if (FAILED(hr))
+       {
+               goto done;
+       }
+/*
+       // Set up event notification.
+       hr = pEvent->SetNotifyWindow((OAHWND)m_hwnd, WM_GRAPH_EVENT, NULL);
+       if (FAILED(hr))
+       {
+               goto done;
+       }
+*/
+//     m_state = STATE_STOPPED;
+
+done:
+       return hr;
+}
+
+void AniPlayerDShowInternal::TearDownGraph()
+{
+/*
+       // Stop sending event messages
+       if (pEvent)
+       {
+               pEvent->SetNotifyWindow((OAHWND)NULL, NULL, NULL);
+       }
+*/
+       SafeRelease(&pGraph);
+       SafeRelease(&pControl);
+       SafeRelease(&pEvent);
+       SafeRelease(&pSeeking);
+
+//     delete m_pVideo;
+//     pVideo = NULL;
+
+//     m_state = STATE_NO_GRAPH;
+}
+
+
+HRESULT AniPlayerDShowInternal::RenderStreams(IBaseFilter *pSource)
+{
+       BOOL bRenderedAnyPin = FALSE;
+
+       IFilterGraph2 *pGraph2 = NULL;
+       IEnumPins *pEnum = NULL;
+       IBaseFilter *pAudioRenderer = NULL;
+       HRESULT hr = pGraph->QueryInterface(IID_PPV_ARGS(&pGraph2));
+       if (FAILED(hr))
+       {
+               goto done;
+       }
+
+       // Add the video renderer to the graph
+       hr = CreateVideoRenderer();
+       if (FAILED(hr))
+       {
+               goto done;
+       }
+
+       // Add the DSound Renderer to the graph.
+       hr = AddFilterByCLSID(pGraph, CLSID_DSoundRender,
+               &pAudioRenderer, L"Audio Renderer");
+       if (FAILED(hr))
+       {
+               goto done;
+       }
+
+       // Enumerate the pins on the source filter.
+       hr = pSource->EnumPins(&pEnum);
+       if (FAILED(hr))
+       {
+               goto done;
+       }
+
+       // Loop through all the pins
+       IPin *pPin;
+       while (S_OK == pEnum->Next(1, &pPin, NULL))
+       {
+               // Try to render this pin.
+               // It's OK if we fail some pins, if at least one pin renders.
+               HRESULT hr2 = pGraph2->RenderEx(pPin, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL);
+
+               pPin->Release();
+               if (SUCCEEDED(hr2))
+               {
+                       bRenderedAnyPin = TRUE;
+               }
+       }
+
+       hr = FinalizeGraph();
+       if (FAILED(hr))
+       {
+               goto done;
+       }
+
+       // Remove the audio renderer, if not used.
+       BOOL bRemoved;
+       hr = RemoveUnconnectedRenderer(pGraph, pAudioRenderer, &bRemoved);
+
+done:
+       SafeRelease(&pEnum);
+       SafeRelease(&pAudioRenderer);
+       SafeRelease(&pGraph2);
+
+       // If we succeeded to this point, make sure we rendered at least one
+       // stream.
+       if (SUCCEEDED(hr))
+       {
+               if (!bRenderedAnyPin)
+               {
+                       hr = VFW_E_CANNOT_RENDER;
+               }
+       }
+       return hr;
+}
+
+HRESULT AniPlayerDShowInternal::RemoveUnconnectedRenderer(IGraphBuilder *pGraph, IBaseFilter *pRenderer, BOOL *pbRemoved)
+{
+       IPin *pPin = NULL;
+
+       *pbRemoved = FALSE;
+
+       // Look for a connected input pin on the renderer.
+
+       HRESULT hr = FindConnectedPin(pRenderer, PINDIR_INPUT, &pPin);
+       SafeRelease(&pPin);
+
+       // If this function succeeds, the renderer is connected, so we don't remove it.
+       // If it fails, it means the renderer is not connected to anything, so
+       // we remove it.
+
+       if (FAILED(hr))
+       {
+               hr = pGraph->RemoveFilter(pRenderer);
+               *pbRemoved = TRUE;
+       }
+
+       return hr;
+}
+
+HRESULT AniPlayerDShowInternal::AddVideoRenderer()
+{
+       IBaseFilter *npEVR = NULL;
+
+       HRESULT hr = AddFilterByCLSID(pGraph, CLSID_EnhancedVideoRenderer, &npEVR, L"EVR");
+
+       if (FAILED(hr))
+       {
+               goto done;
+       }
+
+       hr = InitializeEVR(npEVR, &pVideoDisplay);
+       if (FAILED(hr))
+       {
+               goto done;
+       }
+
+       // Note: Because IMFVideoDisplayControl is a service interface,
+       // you cannot QI the pointer to get back the IBaseFilter pointer.
+       // Therefore, we need to cache the IBaseFilter pointer.
+
+       pEVR = npEVR;
+       pEVR->AddRef();
+
+done:
+       SafeRelease(&npEVR);
+       return hr;
+}
+
+HRESULT AniPlayerDShowInternal::CreateVideoRenderer()
+{
+       HRESULT hr = AddVideoRenderer();
+
+       return hr;
+}
+
+HRESULT AniPlayerDShowInternal::OpenFile(PCWSTR pszFileName)
+{
+       IBaseFilter *pSource = NULL;
+
+       // Create a new filter graph. (This also closes the old one, if any.)
+       HRESULT hr = InitializeGraph();
+       if (FAILED(hr))
+       {
+               goto done;
+       }
+
+       // Add the source filter to the graph.
+       hr = pGraph->AddSourceFilter(pszFileName, NULL, &pSource);
+       if (FAILED(hr))
+       {
+               goto done;
+       }
+
+       // Try to render the streams.
+       hr = RenderStreams(pSource);
+
+done:
+       if (FAILED(hr))
+       {
+               TearDownGraph();
+       }
+       SafeRelease(&pSource);
+       return hr;
+}
+
+HRESULT AniPlayerDShowInternal::Repaint()
+{
+       if (pVideoDisplay)
+       {
+               return pVideoDisplay->RepaintVideo();
+       }
+       else
+       {
+               return S_OK;
+       }
+}
+
+HRESULT AniPlayerDShowInternal::UpdateVideoWindow(const LPRECT prc)
+{
+       if (pVideoDisplay == NULL)
+       {
+               return S_OK; // no-op
+       }
+
+       if (prc)
+       {
+               return pVideoDisplay->SetVideoPosition(NULL, prc);
+       }
+       else
+       {
+
+               RECT rc;
+               GetClientRect(hwnd(), &rc);
+               return pVideoDisplay->SetVideoPosition(NULL, &rc);
+       }
+}
+
+HRESULT AniPlayerDShowInternal::InitializeEVR(IBaseFilter *pEVR, IMFVideoDisplayControl **ppDisplayControl)
+{
+       IMFGetService *pGS = NULL;
+       IMFVideoDisplayControl *pDisplay = NULL;
+
+       HRESULT hr = pEVR->QueryInterface(IID_PPV_ARGS(&pGS));
+       if (FAILED(hr))
+       {
+               goto done;
+       }
+
+       hr = pGS->GetService(MR_VIDEO_RENDER_SERVICE, IID_PPV_ARGS(&pDisplay));
+       if (FAILED(hr))
+       {
+               goto done;
+       }
+
+       // Set the clipping window.
+       hr = pDisplay->SetVideoWindow(hwnd());
+       if (FAILED(hr))
+       {
+               goto done;
+       }
+
+       // Preserve aspect ratio by letter-boxing
+       hr = pDisplay->SetAspectRatioMode(MFVideoARMode_PreservePicture);
+       if (FAILED(hr))
+       {
+               goto done;
+       }
+
+       // Return the IMFVideoDisplayControl pointer to the caller.
+       *ppDisplayControl = pDisplay;
+       (*ppDisplayControl)->AddRef();
+
+done:
+       SafeRelease(&pGS);
+       SafeRelease(&pDisplay);
+       return hr;
+}
+
+HRESULT IsPinConnected(IPin *pPin, BOOL *pResult)
+{
+       IPin *pTmp = NULL;
+       HRESULT hr = pPin->ConnectedTo(&pTmp);
+       if (SUCCEEDED(hr))
+       {
+               *pResult = TRUE;
+       }
+       else if (hr == VFW_E_NOT_CONNECTED)
+       {
+               // The pin is not connected. This is not an error for our purposes.
+               *pResult = FALSE;
+               hr = S_OK;
+       }
+
+       SafeRelease(&pTmp);
+       return hr;
+}
+
+HRESULT IsPinDirection(IPin *pPin, PIN_DIRECTION dir, BOOL *pResult)
+{
+       PIN_DIRECTION pinDir;
+       HRESULT hr = pPin->QueryDirection(&pinDir);
+       if (SUCCEEDED(hr))
+       {
+               *pResult = (pinDir == dir);
+       }
+       return hr;
+}
+
+HRESULT AddFilterByCLSID(IGraphBuilder *pGraph, const GUID &clsid, IBaseFilter **ppF, LPCWSTR wszName)
+{
+       *ppF = 0;
+
+       IBaseFilter *pFilter = NULL;
+
+       HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
+               IID_PPV_ARGS(&pFilter));
+       if (FAILED(hr))
+       {
+               goto done;
+       }
+
+       hr = pGraph->AddFilter(pFilter, wszName);
+       if (FAILED(hr))
+       {
+               goto done;
+       }
+
+       *ppF = pFilter;
+       (*ppF)->AddRef();
+
+done:
+       SafeRelease(&pFilter);
+       return hr;
+}
+
+HRESULT FindConnectedPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin)
+{
+       *ppPin = NULL;
+
+       IEnumPins *pEnum = NULL;
+       IPin *pPin = NULL;
+
+       HRESULT hr = pFilter->EnumPins(&pEnum);
+       if (FAILED(hr))
+       {
+               return hr;
+       }
+
+       BOOL bFound = FALSE;
+       while (S_OK == pEnum->Next(1, &pPin, NULL))
+       {
+               BOOL bIsConnected;
+               hr = IsPinConnected(pPin, &bIsConnected);
+               if (SUCCEEDED(hr))
+               {
+                       if (bIsConnected)
+                       {
+                               hr = IsPinDirection(pPin, PinDir, &bFound);
+                       }
+               }
+
+               if (FAILED(hr))
+               {
+                       pPin->Release();
+                       break;
+               }
+               if (bFound)
+               {
+                       *ppPin = pPin;
+                       break;
+               }
+               pPin->Release();
+       }
+
+       pEnum->Release();
+
+       if (!bFound)
+       {
+               hr = VFW_E_NOT_FOUND;
+       }
+       return hr;
+}
+
+HWND AniPlayerDShowInternal::hwnd() const
+{
+       return (HWND) player->videoWidget()->winId();
+}
+
+
+HRESULT AniPlayerDShowInternal::FinalizeGraph()
+{
+       if (pEVR == NULL)
+       {
+               return S_OK;
+       }
+
+       BOOL bRemoved;
+       HRESULT hr = RemoveUnconnectedRenderer(pGraph, pEVR, &bRemoved);
+       if (bRemoved)
+       {
+               SafeRelease(&pEVR);
+               SafeRelease(&pVideoDisplay);
+       }
+       return hr;
+}
diff --git a/aniplayer2_dshow/aniplayerdshowinternal.h b/aniplayer2_dshow/aniplayerdshowinternal.h
new file mode 100644 (file)
index 0000000..8a72dfe
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef ANIPLAYERDSHOWINTERNAL_H
+#define ANIPLAYERDSHOWINTERNAL_H
+
+#include <QSize>
+
+#include <windows.h>
+
+class AniPlayerDShow;
+
+struct IBaseFilter;
+struct IGraphBuilder;
+struct IMediaControl;
+struct IMediaEvent;
+struct IMediaSeeking;
+struct IMFVideoDisplayControl;
+
+struct AniPlayerDShowInternal
+{
+public:
+       AniPlayerDShowInternal(AniPlayerDShow *player_);
+       ~AniPlayerDShowInternal();
+
+       bool play();
+       bool pause();
+       bool stop();
+
+       QSize videoSize() const;
+
+       HRESULT InitializeGraph();
+       void    TearDownGraph();
+       HRESULT CreateVideoRenderer();
+       HRESULT RenderStreams(IBaseFilter *pSource);
+       HRESULT RemoveUnconnectedRenderer(IGraphBuilder *pGraph, IBaseFilter *pRenderer, BOOL *pbRemoved);
+       HRESULT InitializeEVR(IBaseFilter *pEVR, IMFVideoDisplayControl** ppDisplayControl);
+
+
+       HRESULT AddVideoRenderer();
+       HRESULT FinalizeGraph();
+
+       HRESULT OpenFile(PCWSTR pszFileName);
+
+       IGraphBuilder *pGraph;
+       IMediaControl *pControl;
+       IMediaEvent   *pEvent;
+       IMediaSeeking *pSeeking;
+
+       IBaseFilter                *pEVR;
+       IMFVideoDisplayControl *pVideoDisplay;
+
+       HRESULT Repaint();
+       HRESULT UpdateVideoWindow(const LPRECT prc);
+
+
+       HWND hwnd() const;
+
+       AniPlayerDShow *player;
+};
+
+template <class T> void SafeRelease(T **ppT)
+{
+       if (*ppT)
+       {
+               (*ppT)->Release();
+               *ppT = NULL;
+       }
+}
+
+#endif // ANIPLAYERDSHOWINTERNAL_H
diff --git a/aniplayer2_dshow/videowidgetdshow.cpp b/aniplayer2_dshow/videowidgetdshow.cpp
new file mode 100644 (file)
index 0000000..41cc994
--- /dev/null
@@ -0,0 +1,19 @@
+#include "videowidgetdshow.h"
+
+#include "aniplayerdshow.h"
+
+VideoWidgetDShow::VideoWidgetDShow(AniPlayerDShow *player_, QWidget *parent) :
+       VideoWidget(parent), player(player_)
+{
+       setPalette(QPalette(Qt::black));
+       setAttribute(Qt::WA_OpaquePaintEvent, true);
+       setAttribute(Qt::WA_NoSystemBackground, true);
+       setAttribute(Qt::WA_PaintOnScreen, true);
+       setAutoFillBackground(false);
+}
+
+void VideoWidgetDShow::resizeEvent(QResizeEvent *e)
+{
+       player->widgetChanged();
+       VideoWidget::resizeEvent(e);
+}
diff --git a/aniplayer2_dshow/videowidgetdshow.h b/aniplayer2_dshow/videowidgetdshow.h
new file mode 100644 (file)
index 0000000..1d36cfd
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef VIDEOWIDGETDSHOW_H
+#define VIDEOWIDGETDSHOW_H
+
+#include "aniplayer2_dshow_global.h"
+#include <videowidget.h>
+
+class AniPlayerDShow;
+
+class ANIPLAYER2_DSHOWSHARED_EXPORT VideoWidgetDShow : public VideoWidget
+{
+       Q_OBJECT
+public:
+       explicit VideoWidgetDShow(AniPlayerDShow *player_, QWidget *parent = 0);
+
+       QPaintEngine* paintEngine() const
+       {
+               return 0;
+       }
+signals:
+
+public slots:
+
+protected:
+       void resizeEvent(QResizeEvent *e);
+
+private:
+       AniPlayerDShow *player;
+};
+
+#endif // VIDEOWIDGETDSHOW_H
diff --git a/config.pri b/config.pri
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/player/main.cpp b/player/main.cpp
new file mode 100644 (file)
index 0000000..0063be9
--- /dev/null
@@ -0,0 +1,11 @@
+#include "mainwindow.h"
+#include <QApplication>
+
+int main(int argc, char *argv[])
+{
+       QApplication a(argc, argv);
+       MainWindow w;
+       w.show();
+       
+       return a.exec();
+}
diff --git a/player/mainwindow.cpp b/player/mainwindow.cpp
new file mode 100644 (file)
index 0000000..2c7dbef
--- /dev/null
@@ -0,0 +1,32 @@
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+
+#ifdef Q_OS_WIN
+#      include <aniplayerdshow.h>
+#endif
+
+#include <videowidget.h>
+
+MainWindow::MainWindow(QWidget *parent) :
+       QMainWindow(parent),
+       ui(new Ui::MainWindow)
+{
+       player = new AniPlayerDShow(this);
+
+       player->open("E:/Anime/Accel World OVA/Accel World OVA - 01 - OVA - [UTW][3e56ee18].mkv");
+       player->play();
+
+       ui->setupUi(this);
+
+       QAction *a = new QAction("Pause", this);
+       a->setShortcut(QKeySequence("Space"));
+       connect(a, SIGNAL(triggered()), player, SLOT(togglePause()));
+       addAction(a);
+
+       setCentralWidget(player->videoWidget());
+}
+
+MainWindow::~MainWindow()
+{
+       delete ui;
+}
diff --git a/player/mainwindow.h b/player/mainwindow.h
new file mode 100644 (file)
index 0000000..b87b77c
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+
+namespace Ui {
+class MainWindow;
+}
+
+class AniPlayer;
+
+class MainWindow : public QMainWindow
+{
+       Q_OBJECT
+       
+public:
+       explicit MainWindow(QWidget *parent = 0);
+       ~MainWindow();
+       
+private:
+       Ui::MainWindow *ui;
+
+       AniPlayer *player;
+};
+
+#endif // MAINWINDOW_H
diff --git a/player/mainwindow.ui b/player/mainwindow.ui
new file mode 100644 (file)
index 0000000..6050363
--- /dev/null
@@ -0,0 +1,24 @@
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>MainWindow</string>
+  </property>
+  <widget class="QMenuBar" name="menuBar" />
+  <widget class="QToolBar" name="mainToolBar" />
+  <widget class="QWidget" name="centralWidget" />
+  <widget class="QStatusBar" name="statusBar" />
+ </widget>
+ <layoutDefault spacing="6" margin="11" />
+ <pixmapfunction></pixmapfunction>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/player/player.pro b/player/player.pro
new file mode 100644 (file)
index 0000000..b1c0092
--- /dev/null
@@ -0,0 +1,20 @@
+QT += core gui
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+TEMPLATE = app
+
+TARGET = player
+DESTDIR = ../build
+
+
+SOURCES += main.cpp\
+        mainwindow.cpp
+
+HEADERS  += mainwindow.h
+
+FORMS    += mainwindow.ui
+
+include(../config.pri)
+include(../aniplayer2/aniplayer2.pri)
+win32:include(../aniplayer2_dshow/aniplayer2_dshow.pri)