summaryrefslogtreecommitdiffstats
path: root/plugins/pluginDirectShow/internals
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/pluginDirectShow/internals')
-rw-r--r--plugins/pluginDirectShow/internals/DSBaseCaptureGraph.h64
-rw-r--r--plugins/pluginDirectShow/internals/DSBufferWriter.h48
-rw-r--r--plugins/pluginDirectShow/internals/DSCaptureFormat.cxx60
-rw-r--r--plugins/pluginDirectShow/internals/DSCaptureFormat.h47
-rw-r--r--plugins/pluginDirectShow/internals/DSCaptureGraph.cxx436
-rw-r--r--plugins/pluginDirectShow/internals/DSCaptureGraph.h106
-rw-r--r--plugins/pluginDirectShow/internals/DSCaptureUtils.cxx377
-rw-r--r--plugins/pluginDirectShow/internals/DSCaptureUtils.h60
-rw-r--r--plugins/pluginDirectShow/internals/DSDibHelper.cxx80
-rw-r--r--plugins/pluginDirectShow/internals/DSDibHelper.h106
-rw-r--r--plugins/pluginDirectShow/internals/DSDisplay.cxx622
-rw-r--r--plugins/pluginDirectShow/internals/DSDisplay.h84
-rw-r--r--plugins/pluginDirectShow/internals/DSDisplayGraph.cxx345
-rw-r--r--plugins/pluginDirectShow/internals/DSDisplayGraph.h110
-rw-r--r--plugins/pluginDirectShow/internals/DSDisplayOverlay.VMR.cxx179
-rw-r--r--plugins/pluginDirectShow/internals/DSDisplayOverlay.VMR9.cxx207
-rw-r--r--plugins/pluginDirectShow/internals/DSDisplayOverlay.cxx67
-rw-r--r--plugins/pluginDirectShow/internals/DSDisplayOverlay.h68
-rw-r--r--plugins/pluginDirectShow/internals/DSFrameRateFilter.cxx120
-rw-r--r--plugins/pluginDirectShow/internals/DSFrameRateFilter.h64
-rw-r--r--plugins/pluginDirectShow/internals/DSGrabber.cxx292
-rw-r--r--plugins/pluginDirectShow/internals/DSGrabber.h92
-rw-r--r--plugins/pluginDirectShow/internals/DSOutputFilter.cxx113
-rw-r--r--plugins/pluginDirectShow/internals/DSOutputFilter.h112
-rw-r--r--plugins/pluginDirectShow/internals/DSOutputStream.cxx313
-rw-r--r--plugins/pluginDirectShow/internals/DSOutputStream.h90
-rw-r--r--plugins/pluginDirectShow/internals/DSPushSource.h496
-rw-r--r--plugins/pluginDirectShow/internals/DSPushSourceDesktop.cxx434
-rw-r--r--plugins/pluginDirectShow/internals/DSScreenCastGraph.cxx257
-rw-r--r--plugins/pluginDirectShow/internals/DSScreenCastGraph.h160
-rw-r--r--plugins/pluginDirectShow/internals/DSUtils.cxx365
-rw-r--r--plugins/pluginDirectShow/internals/DSUtils.h82
-rw-r--r--plugins/pluginDirectShow/internals/Resizer.cxx1192
-rw-r--r--plugins/pluginDirectShow/internals/Resizer.h76
-rw-r--r--plugins/pluginDirectShow/internals/VideoDisplayName.cxx37
-rw-r--r--plugins/pluginDirectShow/internals/VideoDisplayName.h43
-rw-r--r--plugins/pluginDirectShow/internals/VideoFrame.h107
-rw-r--r--plugins/pluginDirectShow/internals/VideoGrabberName.cxx37
-rw-r--r--plugins/pluginDirectShow/internals/VideoGrabberName.h43
-rw-r--r--plugins/pluginDirectShow/internals/wince/CPropertyBag.cxx108
-rw-r--r--plugins/pluginDirectShow/internals/wince/CPropertyBag.h43
-rw-r--r--plugins/pluginDirectShow/internals/wince/DSISampleGrabberCB.h30
-rw-r--r--plugins/pluginDirectShow/internals/wince/DSNullFilter.cxx56
-rw-r--r--plugins/pluginDirectShow/internals/wince/DSNullFilter.h40
-rw-r--r--plugins/pluginDirectShow/internals/wince/DSSampleGrabber.cxx197
-rw-r--r--plugins/pluginDirectShow/internals/wince/DSSampleGrabber.h73
-rw-r--r--plugins/pluginDirectShow/internals/wince/DSSampleGrabberUtils.h38
47 files changed, 8176 insertions, 0 deletions
diff --git a/plugins/pluginDirectShow/internals/DSBaseCaptureGraph.h b/plugins/pluginDirectShow/internals/DSBaseCaptureGraph.h
new file mode 100644
index 0000000..1817fb5
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSBaseCaptureGraph.h
@@ -0,0 +1,64 @@
+/* Copyright (C) 2014 Mamadou DIOP
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#ifndef PLUGIN_DSHOW_DSBASECAPTUREGRAPH_H
+#define PLUGIN_DSHOW_DSBASECAPTUREGRAPH_H
+
+#include "plugin_dshow_config.h"
+
+#include <vector>
+#include <control.h>
+#include "internals/DSCaptureFormat.h"
+
+#if defined(_WIN32_WCE)
+# include <internals/wince/DSSampleGrabber.h>
+# include <internals/wince/DSNullFilter.h>
+# include <internals/wince/DSISampleGrabberCB.h>
+#else
+# include <qedit.h>
+#endif
+
+class DSBaseCaptureGraph
+{
+public:
+#if defined(_WIN32_WCE)
+ DSBaseCaptureGraph(DSISampleGrabberCB* callback, HRESULT *hr) {}
+#else
+ DSBaseCaptureGraph(ISampleGrabberCB* callback, HRESULT *hr) {}
+#endif
+ virtual ~DSBaseCaptureGraph() {}
+
+ virtual std::vector<DSCaptureFormat> *getFormats() = 0;
+
+ virtual HRESULT setSource(const std::string &devicePath) = 0;
+ virtual HRESULT setParameters(DSCaptureFormat *format, int framerate) = 0;
+
+ virtual HRESULT connect() = 0;
+ virtual HRESULT disconnect() = 0;
+
+ virtual HRESULT start() = 0;
+ virtual HRESULT stop() = 0;
+ virtual HRESULT pause() = 0;
+ virtual bool isRunning() = 0;
+ virtual bool isPaused() = 0;
+
+ virtual std::string getDeviceId() const = 0;
+
+ virtual HRESULT getConnectedMediaType(AM_MEDIA_TYPE *mediaType) = 0;
+};
+
+#endif /* PLUGIN_DSHOW_DSBASECAPTUREGRAPH_H */
diff --git a/plugins/pluginDirectShow/internals/DSBufferWriter.h b/plugins/pluginDirectShow/internals/DSBufferWriter.h
new file mode 100644
index 0000000..dbe1484
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSBufferWriter.h
@@ -0,0 +1,48 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#ifndef PLUGIN_DSHOW_DSBUFFERWRITTER_H
+#define PLUGIN_DSHOW_DSBUFFERWRITTER_H
+/*
+// TODO: do it only once
+#if !defined(TDSHOW_DEFINE_GUID) && !defined(_WIN32_WCE)
+#define TDSHOW_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ EXTERN_C const GUID DECLSPEC_SELECTANY name \
+ = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
+#elif !defined(TDSHOW_DEFINE_GUID) && defined(_WIN32_WCE)
+#define TDSHOW_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ EXTERN_C const GUID __declspec(selectany) name \
+ = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
+#endif
+
+// {27AD9929-E4E7-423b-8BDD-8AF5AC894DE0}
+TDSHOW_DEFINE_GUID(IID_DSBufferWriter,
+ 0x27ad9929, 0xe4e7, 0x423b, 0x8b, 0xdd, 0x8a, 0xf5, 0xac, 0x89, 0x4d, 0xe0);
+ */
+
+
+class DSBufferWriter
+#ifndef _WIN32_WCE
+ : public IUnknown
+#endif
+{
+public:
+ virtual void setBuffer (void* pBuffer, int size) = 0;
+ virtual HRESULT setImageFormat(UINT width, UINT height/*, GUID subType, UINT fps*/) = 0;
+};
+
+#endif
diff --git a/plugins/pluginDirectShow/internals/DSCaptureFormat.cxx b/plugins/pluginDirectShow/internals/DSCaptureFormat.cxx
new file mode 100644
index 0000000..378a215
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSCaptureFormat.cxx
@@ -0,0 +1,60 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#include "internals/DSCaptureFormat.h"
+#include <uuids.h>
+
+
+int DSCaptureFormat::getMatchScore(int w, int h)
+{
+ int factor;
+
+ if ((w == width) && (h = height)){
+ factor = 100;
+ }
+ else if ((w > this->width) && (h > this->height)){
+ factor = 0;
+ }
+ else{
+ factor = (50 * w) / this->width + (50 * h) / this->height;
+ }
+
+ if (isRGB()){
+ factor *= 2;
+ }
+
+ return factor;
+}
+
+bool DSCaptureFormat::isRGB()
+{
+ // Order used is optimized for most used RGB types
+ if (IsEqualGUID(this->chroma, MEDIASUBTYPE_RGB32)) return true;
+ if (IsEqualGUID(this->chroma, MEDIASUBTYPE_RGB24)) return true;
+ if (IsEqualGUID(this->chroma, MEDIASUBTYPE_RGB565)) return true;
+ if (IsEqualGUID(this->chroma, MEDIASUBTYPE_RGB555)) return true;
+ if (IsEqualGUID(this->chroma, MEDIASUBTYPE_RGB8)) return true;
+ if (IsEqualGUID(this->chroma, MEDIASUBTYPE_RGB4)) return true;
+ if (IsEqualGUID(this->chroma, MEDIASUBTYPE_RGB1)) return true;
+#ifndef _WIN32_WCE
+ if (IsEqualGUID(this->chroma, MEDIASUBTYPE_ARGB32)) return true;
+ if (IsEqualGUID(this->chroma, MEDIASUBTYPE_ARGB4444)) return true;
+ if (IsEqualGUID(this->chroma, MEDIASUBTYPE_ARGB1555)) return true;
+#endif
+
+ return false;
+}
diff --git a/plugins/pluginDirectShow/internals/DSCaptureFormat.h b/plugins/pluginDirectShow/internals/DSCaptureFormat.h
new file mode 100644
index 0000000..5e1cabb
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSCaptureFormat.h
@@ -0,0 +1,47 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#ifndef PLUGIN_DSHOW_DSCAPTUREFORMAT_H
+#define PLUGIN_DSHOW_DSCAPTUREFORMAT_H
+
+#include "plugin_dshow_config.h"
+#include <strmif.h>
+
+
+class DSCaptureFormat
+{
+public:
+ DSCaptureFormat(int w, int h, int f, GUID c) : width(w), height(h), fps(f), chroma(c) {};
+ virtual ~DSCaptureFormat() {};
+
+ int getWidth() { return this->width; };
+ int getHeight() { return this->height; };
+ int getFramerate() { return this->fps; };
+ GUID getChroma() { return this->chroma; };
+
+ int getMatchScore(int w, int h);
+ bool isRGB();
+
+private:
+ int width;
+ int height;
+ int fps;
+ GUID chroma;
+};
+
+
+#endif
diff --git a/plugins/pluginDirectShow/internals/DSCaptureGraph.cxx b/plugins/pluginDirectShow/internals/DSCaptureGraph.cxx
new file mode 100644
index 0000000..3da6da1
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSCaptureGraph.cxx
@@ -0,0 +1,436 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#include "internals/DSCaptureGraph.h"
+#include "internals/DSUtils.h"
+#include "internals/DSCaptureUtils.h"
+
+#include "tsk_debug.h"
+
+#include <iostream>
+
+using namespace std;
+
+#ifdef _WIN32_WCE
+DSCaptureGraph::DSCaptureGraph(DSISampleGrabberCB* callback, HRESULT *hr)
+: DSBaseCaptureGraph(callback, hr)
+#else
+DSCaptureGraph::DSCaptureGraph(ISampleGrabberCB* callback, HRESULT *hr)
+: DSBaseCaptureGraph(callback, hr)
+#endif
+{
+ this->grabberCallback = callback;
+
+ this->captureFormat = NULL;
+ this->captureGraphBuilder = NULL;
+ this->graphBuilder = NULL;
+
+ this->sourceFilter = NULL;
+ this->sampleGrabberFilter = NULL;
+
+#ifdef _WIN32_WCE
+ this->colorConvertor565 = NULL;
+#else
+ this->frameRateFilter = NULL;
+#endif
+
+ this->nullRendererFilter = NULL;
+ this->grabberController = NULL;
+ this->mediaController = NULL;
+ this->mediaEventController = NULL;
+
+ this->streamConfiguration = NULL;
+
+ this->running = FALSE;
+ this->paused = FALSE;
+ this->deviceId = "";
+
+ *hr = this->createCaptureGraph();
+}
+
+DSCaptureGraph::~DSCaptureGraph()
+{
+ SAFE_RELEASE(this->streamConfiguration);
+
+ SAFE_RELEASE(this->mediaEventController);
+ SAFE_RELEASE(this->mediaController);
+ SAFE_RELEASE(this->grabberController);
+
+#if defined(_WIN32_WCE)
+ SAFE_RELEASE(this->colorConvertor565);
+#else
+#endif
+
+ SAFE_RELEASE(this->nullRendererFilter);
+ SAFE_RELEASE(this->sampleGrabberFilter);
+ SAFE_RELEASE(this->sourceFilter);
+
+ SAFE_RELEASE(this->graphBuilder);
+ SAFE_RELEASE(this->captureGraphBuilder);
+}
+
+HRESULT DSCaptureGraph::setSource(const std::string &devicePath)
+{
+ HRESULT hr = E_FAIL;
+
+ if (this->sourceFilter){
+ this->graphBuilder->RemoveFilter(this->sourceFilter);
+ }
+
+ SAFE_RELEASE(this->streamConfiguration);
+ SAFE_RELEASE(this->sourceFilter);
+
+ // Create the filter
+ this->deviceId = devicePath;
+ hr = createSourceFilter(&this->deviceId, &this->sourceFilter);
+
+ if (this->sourceFilter){
+ // Gets the supported formats
+ this->supportedFormats.clear();
+ getSupportedFormats(this->sourceFilter, &this->supportedFormats);
+
+ // Query for video stream config
+ hr = this->captureGraphBuilder->FindInterface(
+ &PIN_CATEGORY_CAPTURE,
+ &MEDIATYPE_Video,
+ this->sourceFilter,
+ IID_IAMStreamConfig,
+ reinterpret_cast<void**>(&this->streamConfiguration));
+
+ hr = this->graphBuilder->AddFilter(this->sourceFilter, FILTER_WEBCAM);
+ }
+
+ return hr;
+}
+
+HRESULT DSCaptureGraph::setParameters(DSCaptureFormat *format, int framerate)
+{
+ HRESULT hr = E_FAIL;
+ AM_MEDIA_TYPE *mediaType = NULL;
+
+ if (!this->streamConfiguration) goto bail;
+
+ hr = this->streamConfiguration->GetFormat(&mediaType);
+ if (FAILED(hr)) goto bail;
+
+ VIDEOINFOHEADER* vih = reinterpret_cast<VIDEOINFOHEADER*>(mediaType->pbFormat);
+ BITMAPINFOHEADER* bih = &vih->bmiHeader;
+
+ int w = format->getWidth();
+ int h = format->getHeight();
+
+ bool wN = (bih->biWidth<0);
+ bool hN = (bih->biHeight<0);
+
+ // DIBS are DWORD aligned
+ int data_size = h * ((w * bih->biBitCount + 31) / 32) * 4;
+
+ bih->biSize = sizeof(BITMAPINFOHEADER);
+ bih->biWidth = w*(wN?-1:1);
+ bih->biHeight = h*(hN?-1:1);
+ bih->biSizeImage = data_size;
+
+ //vih->dwBitRate = framerate * data_size;
+ //vih->AvgTimePerFrame = SECONDS_TO_100NS(framerate);
+
+ mediaType->cbFormat = sizeof(VIDEOINFOHEADER);
+ //mediaType->lSampleSize = data_size;
+ mediaType->subtype = format->getChroma();
+
+ hr = this->streamConfiguration->SetFormat(mediaType);
+ if (FAILED(hr)) goto bail;
+
+#if defined(_WIN32_WCE)
+ hr = this->grabberController->SetFps((int) DS_SECONDS_FROM_100NS(vih->AvgTimePerFrame)/*format->getFramerate()*/, framerate);
+ if (FAILED(hr)) goto bail;
+ hr = this->grabberController->SetSize(w,h);
+#else
+ // Set fps using tdshow filter
+ hr = this->frameRateFilter->SetFps((int) ((float)vih->AvgTimePerFrame/10000.f)/*format->getFramerate()*/, framerate);
+#endif
+ if (FAILED(hr)) goto bail;
+
+ this->captureFormat = format;
+
+bail:
+ DeleteMediaType(mediaType);
+
+ return hr;
+}
+
+#if defined(_WIN32_WCE)
+# include "internals/wince/DSNullFilter.h"
+#endif
+
+HRESULT DSCaptureGraph::connect()
+{
+ HRESULT hr;
+
+ if (!this->sourceFilter){
+ TSK_DEBUG_ERROR("Invalid source filter");
+ return E_FAIL;
+ }
+
+ if (!this->captureFormat){
+ TSK_DEBUG_ERROR("Invalid capture format");
+ return E_FAIL;
+ }
+
+ if (!this->graphBuilder){
+ TSK_DEBUG_ERROR("Invalid grash builder");
+ return E_FAIL;
+ }
+
+ if (this->captureFormat->isRGB())
+ {
+#if defined(_WIN32_WCE)
+ hr = ConnectFilters(this->graphBuilder, this->sourceFilter, this->colorConvertor565) ; if(FAILED(hr)) { TSK_DEBUG_ERROR("ConnectFilters failed"); return hr; }
+ hr = ConnectFilters(this->graphBuilder, this->colorConvertor565, this->sampleGrabberFilter) ; if(FAILED(hr)) { TSK_DEBUG_ERROR("ConnectFilters failed"); return hr; }
+ hr = ConnectFilters(this->graphBuilder, this->sampleGrabberFilter, this->nullRendererFilter); if(FAILED(hr)) { TSK_DEBUG_ERROR("ConnectFilters failed"); return hr; }
+#else
+ hr = ConnectFilters(this->graphBuilder, this->sourceFilter, this->frameRateFilter); if(FAILED(hr)) { TSK_DEBUG_ERROR("ConnectFilters failed"); return hr; }
+ hr = ConnectFilters(this->graphBuilder, this->frameRateFilter, this->sampleGrabberFilter); if(FAILED(hr)) { TSK_DEBUG_ERROR("ConnectFilters failed"); return hr; }
+ hr = ConnectFilters(this->graphBuilder, this->sampleGrabberFilter, this->nullRendererFilter); if(FAILED(hr)) { TSK_DEBUG_ERROR("ConnectFilters failed"); return hr; }
+#endif
+ }
+ else
+ {
+#if defined(_WIN32_WCE)
+ hr = ConnectFilters(this->graphBuilder, this->sourceFilter, this->colorConvertor565) ; if(FAILED(hr))return hr;
+ hr = ConnectFilters(this->graphBuilder, this->colorConvertor565, this->sampleGrabberFilter) ; if(FAILED(hr))return hr;
+ hr = ConnectFilters(this->graphBuilder, this->sampleGrabberFilter, this->nullRendererFilter); if(FAILED(hr))return hr;
+#else
+ // No convertor needed
+ // AVI Decompressor Filter is automatically by the Filter Graph Manager when needed
+ hr = ConnectFilters(this->graphBuilder, this->sourceFilter, this->frameRateFilter); if(FAILED(hr)) { TSK_DEBUG_ERROR("ConnectFilters failed"); return hr; }
+ hr = ConnectFilters(this->graphBuilder, this->frameRateFilter, this->sampleGrabberFilter); if(FAILED(hr)) { TSK_DEBUG_ERROR("ConnectFilters failed"); return hr; }
+ hr = ConnectFilters(this->graphBuilder, this->sampleGrabberFilter, this->nullRendererFilter); if(FAILED(hr)) { TSK_DEBUG_ERROR("ConnectFilters failed"); return hr; }
+#endif
+ }
+
+ return hr;
+}
+
+HRESULT DSCaptureGraph::disconnect()
+{
+ HRESULT hr;
+
+ if (!this->sourceFilter) {
+ return E_FAIL;
+ }
+
+ if (!this->captureFormat) {
+ return E_FAIL;
+ }
+
+ if (this->captureFormat->isRGB())
+ {
+#if defined(_WIN32_WCE)
+ hr = DisconnectFilters(this->graphBuilder, this->sourceFilter, this->colorConvertor565);
+ hr = DisconnectFilters(this->graphBuilder, this->colorConvertor565, this->sampleGrabberFilter);
+ hr = DisconnectFilters(this->graphBuilder, this->sampleGrabberFilter, this->nullRendererFilter);
+#else
+ hr = DisconnectFilters(this->graphBuilder, this->sourceFilter, this->frameRateFilter);
+ hr = DisconnectFilters(this->graphBuilder, this->frameRateFilter, this->sampleGrabberFilter);
+ hr = DisconnectFilters(this->graphBuilder, this->sampleGrabberFilter, this->nullRendererFilter);
+#endif
+ }
+ else
+ {
+#if defined(_WIN32_WCE)
+ hr = DisconnectFilters(this->graphBuilder, this->sourceFilter, this->colorConvertor565); if(FAILED(hr))return hr;
+ hr = DisconnectFilters(this->graphBuilder, this->colorConvertor565, this->sampleGrabberFilter); if(FAILED(hr))return hr;
+ hr = DisconnectFilters(this->graphBuilder, this->sampleGrabberFilter, this->nullRendererFilter); if(FAILED(hr))return hr;
+#else
+ hr = DisconnectFilters(this->graphBuilder, this->sourceFilter, this->frameRateFilter);
+ hr = DisconnectFilters(this->graphBuilder, this->frameRateFilter, this->sampleGrabberFilter);
+ hr = DisconnectFilters(this->graphBuilder, this->sampleGrabberFilter, this->nullRendererFilter);
+#endif
+ }
+
+ return hr;
+}
+
+HRESULT DSCaptureGraph::start()
+{
+ HRESULT hr;
+
+ if (isRunning() && !isPaused()) {
+ return S_OK;
+ }
+
+ //this->mediaController->Stop();
+
+ hr = this->mediaController ? this->mediaController->Run() : E_POINTER;
+ /*if (hr == S_FALSE)
+ {
+ cerr << "DSCaptureGraph::mediaController->Start() has failed with " << hr << ". Waiting for transition." << endl;
+ FILTER_STATE pfs;
+ hr = this->mediaController->GetState(2500, (OAFilterState*) &pfs);
+ hr = this->mediaController->Run();
+ }*/
+
+ if (!SUCCEEDED(hr))
+ {
+#if defined(_WIN32_WCE)
+ MessageBox(NULL, _T("Starting DirectShow Graph Failed"), _T("Failure"), MB_OK);
+ //assert(1==15);
+#endif
+ TSK_DEBUG_ERROR("DSCaptureGraph::mediaController->Run() has failed with %ld", hr);
+ return hr;
+ }
+ this->running = true;
+ return hr;
+}
+
+HRESULT DSCaptureGraph::pause()
+{
+ HRESULT hr = S_OK;
+ if (isRunning()) {
+ hr = this->mediaController->Pause();
+ if (SUCCEEDED(hr)) {
+ this->paused = TRUE;
+ }
+ }
+ return hr;
+}
+
+HRESULT DSCaptureGraph::stop()
+{
+ HRESULT hr;
+#if 0 // Must not
+ hr = this->mediaController->Pause();
+ if (hr == S_FALSE)
+ {
+ TSK_DEBUG_ERROR("DSCaptureGraph::mediaController->Pause() has failed with %ld. Waiting for transition.", hr);
+ FILTER_STATE pfs;
+ hr = this->mediaController->GetState(2500, (OAFilterState*) &pfs);
+ }
+#endif
+ hr = this->mediaController->Stop();
+ if (!SUCCEEDED(hr))
+ {
+ TSK_DEBUG_ERROR("DSCaptureGraph::mediaController->Stop() has failed with %ld", hr);
+ }
+ this->running = false;
+ this->paused = false;
+ return hr;
+}
+
+bool DSCaptureGraph::isRunning()
+{
+ return this->running;
+}
+
+bool DSCaptureGraph::isPaused()
+{
+ return this->paused;
+}
+
+HRESULT DSCaptureGraph::getConnectedMediaType(AM_MEDIA_TYPE *mediaType)
+{
+#if defined(_WIN32_WCE)
+ memmove(mediaType, &this->grabberController->GetMediaType(), sizeof(AM_MEDIA_TYPE));
+ return S_OK;
+#else
+ return this->grabberController->GetConnectedMediaType(mediaType);
+#endif
+}
+
+HRESULT DSCaptureGraph::createCaptureGraph()
+{
+ HRESULT hr;
+
+#if defined(_WIN32_WCE)
+ // Create capture graph builder
+ CHECK_HR(hr = COCREATE(CLSID_CaptureGraphBuilder, IID_ICaptureGraphBuilder2, this->captureGraphBuilder));
+ CHECK_HR(hr = COCREATE(CLSID_FilterGraph, IID_IGraphBuilder, this->graphBuilder));
+ CHECK_HR(hr = this->captureGraphBuilder->SetFiltergraph(this->graphBuilder));
+
+ // Create filters
+ LPUNKNOWN pUnk1 = NULL, pUnk2 = NULL;
+ CHECK_HR(hr = COCREATE(CLSID_Colour, IID_IBaseFilter, this->colorConvertor565));
+ this->sampleGrabberFilter = new DSSampleGrabber(FITLER_SAMPLE_GRABBER, pUnk1, &hr); CHECK_HR(hr);
+ this->nullRendererFilter = new DSNullFilter(/*FILTER_NULL_RENDERER,*/ pUnk2, &hr); CHECK_HR(hr);
+ this->grabberController = (DSSampleGrabber*)(this->sampleGrabberFilter); if (!this->grabberController) CHECK_HR(E_FAIL);
+
+ // Add Filters
+ CHECK_HR(hr = this->graphBuilder->AddFilter(this->colorConvertor565, FILTER_COLOR_CONVERTOR_565));
+ CHECK_HR(hr = this->graphBuilder->AddFilter(this->sampleGrabberFilter, FITLER_SAMPLE_GRABBER));
+ CHECK_HR(hr = this->graphBuilder->AddFilter(this->nullRendererFilter, FILTER_NULL_RENDERER));
+
+ // Find media control
+ CHECK_HR(hr = QUERY(this->graphBuilder, IID_IMediaControl, this->mediaController));
+
+ // Set callback
+ CHECK_HR(hr = this->grabberController->SetCallback(this->grabberCallback));
+#else
+ // Create capture graph builder
+ CHECK_HR(hr = COCREATE(CLSID_CaptureGraphBuilder2, IID_ICaptureGraphBuilder2, this->captureGraphBuilder));
+
+ // Create the graph builder
+ CHECK_HR(hr = COCREATE(CLSID_FilterGraph, IID_IGraphBuilder, this->graphBuilder));
+
+ // Initialize the Capture Graph Builder.
+ CHECK_HR(hr = this->captureGraphBuilder->SetFiltergraph(this->graphBuilder));
+
+ // Create the sample grabber filter
+ CHECK_HR(hr = COCREATE(CLSID_SampleGrabber, IID_IBaseFilter, this->sampleGrabberFilter));
+
+ // Create tdshow filter
+ LPUNKNOWN pUnk = NULL;
+ this->frameRateFilter = new DSFrameRateFilter(FILTER_FRAMERATE, pUnk, &hr); CHECK_HR(hr);
+ if (!this->frameRateFilter == NULL) CHECK_HR(E_FAIL);
+
+ // Create the NULL renderer
+ CHECK_HR(hr = COCREATE(CLSID_NullRenderer, IID_IBaseFilter, this->nullRendererFilter));
+
+ // Add sample grabber to the graph
+ CHECK_HR(hr = this->graphBuilder->AddFilter(this->sampleGrabberFilter, FITLER_SAMPLE_GRABBER));
+
+ // Add null renderer to the graph
+ CHECK_HR(hr = this->graphBuilder->AddFilter(this->nullRendererFilter, FILTER_NULL_RENDERER));
+
+ // Add tdshow filter
+ CHECK_HR(hr = this->graphBuilder->AddFilter(this->frameRateFilter, FILTER_FRAMERATE));
+
+ // Find media control
+ CHECK_HR(hr = QUERY(this->graphBuilder, IID_IMediaControl, this->mediaController));
+
+ // Create the sample grabber
+ CHECK_HR(hr = QUERY(this->sampleGrabberFilter, IID_ISampleGrabber, this->grabberController));
+
+ // Set the sample grabber media type (RGB24)
+ // TODO : CHECK
+ AM_MEDIA_TYPE mt;
+ ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
+ mt.majortype = MEDIATYPE_Video;
+ mt.subtype = MEDIASUBTYPE_RGB24;
+ mt.formattype = FORMAT_VideoInfo;
+
+ CHECK_HR(hr = this->grabberController->SetMediaType(&mt));
+
+ // Set sample grabber media type
+ this->grabberController->SetOneShot(FALSE);
+ this->grabberController->SetBufferSamples(FALSE);
+
+ CHECK_HR(hr = this->grabberController->SetCallback(this->grabberCallback, 1));
+#endif
+
+bail:
+ return hr;
+} \ No newline at end of file
diff --git a/plugins/pluginDirectShow/internals/DSCaptureGraph.h b/plugins/pluginDirectShow/internals/DSCaptureGraph.h
new file mode 100644
index 0000000..6bf8862
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSCaptureGraph.h
@@ -0,0 +1,106 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#ifndef PLUGIN_DSHOW_DSCAPTUREGRAPH_H
+#define PLUGIN_DSHOW_DSCAPTUREGRAPH_H
+
+#include "plugin_dshow_config.h"
+#include <vector>
+#include <control.h>
+#include "internals/DSBaseCaptureGraph.h"
+#include "internals/DSFrameRateFilter.h"
+
+#if defined(_WIN32_WCE)
+# include "internals/wince/DSSampleGrabber.h"
+# include "internals/wince/DSNullFilter.h"
+# include "internals/wince/DSISampleGrabberCB.h"
+#else
+# include <qedit.h>
+#endif
+
+
+class DSCaptureGraph : public DSBaseCaptureGraph
+{
+public:
+#ifdef _WIN32_WCE
+ DSCaptureGraph(DSISampleGrabberCB* callback, HRESULT *hr);
+#else
+ DSCaptureGraph(ISampleGrabberCB* callback, HRESULT *hr);
+#endif
+ virtual ~DSCaptureGraph();
+
+ std::vector<DSCaptureFormat> *getFormats() { return &this->supportedFormats; };
+
+ HRESULT setSource(const std::string &devicePath);
+ HRESULT setParameters(DSCaptureFormat *format, int framerate);
+
+ HRESULT connect();
+ HRESULT disconnect();
+
+ HRESULT start();
+ HRESULT stop();
+ HRESULT pause();
+ bool isRunning();
+ bool isPaused();
+
+ std::string getDeviceId() const { return this->deviceId; };
+
+ HRESULT getConnectedMediaType(AM_MEDIA_TYPE *mediaType);
+
+private:
+ HRESULT createCaptureGraph();
+
+private:
+#ifdef _WIN32_WCE
+ DSISampleGrabberCB *grabberCallback;
+#else
+ ISampleGrabberCB *grabberCallback;
+#endif
+
+ ICaptureGraphBuilder2 *captureGraphBuilder;
+ IGraphBuilder *graphBuilder;
+
+ IBaseFilter *sourceFilter;
+ IBaseFilter *nullRendererFilter;
+ IBaseFilter *sampleGrabberFilter;
+
+#ifdef _WIN32_WCE
+ IBaseFilter *colorConvertor565; //http://msdn.microsoft.com/en-us/library/aa926076.aspx
+#else
+ DSFrameRateFilter *frameRateFilter;
+#endif
+
+#ifdef _WIN32_WCE
+ DSSampleGrabber *grabberController;
+#else
+ ISampleGrabber *grabberController;
+#endif
+
+ IMediaControl *mediaController;
+ IMediaEventEx *mediaEventController;
+
+ IAMStreamConfig *streamConfiguration;
+
+ std::vector<DSCaptureFormat> supportedFormats;
+ DSCaptureFormat *captureFormat;
+
+ bool running;
+ bool paused;
+ std::string deviceId;
+};
+
+#endif
diff --git a/plugins/pluginDirectShow/internals/DSCaptureUtils.cxx b/plugins/pluginDirectShow/internals/DSCaptureUtils.cxx
new file mode 100644
index 0000000..d95f996
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSCaptureUtils.cxx
@@ -0,0 +1,377 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#include "internals/DSUtils.h"
+#include "internals/DSCaptureUtils.h"
+#include <amvideo.h>
+#include <uuids.h>
+#include <mtype.h>
+
+#if defined (_WIN32_WCE)
+#include <atlbase.h>
+#include <atlstr.h>
+#else
+#include <atlconv.h>
+#endif
+#include <iostream>
+#include <assert.h>
+
+#include "tsk_debug.h"
+
+#if defined (_WIN32_WCE)
+# include "internals/wince/cpropertybag.h"
+#endif
+
+HRESULT enumerateCaptureDevices(const std::string &prefix, std::vector<VideoGrabberName> *names)
+{
+ HRESULT hr = S_OK;
+
+#ifdef _WIN32_WCE
+
+ // FIXME: use FindNextDevice to query all devices
+ HANDLE handle = NULL;
+ DEVMGR_DEVICE_INFORMATION di;
+
+ TCHAR pwzName[MAX_PATH]; memset(pwzName,NULL,MAX_PATH);
+
+ GUID guidCamera = { 0xCB998A05, 0x122C, 0x4166, 0x84, 0x6A,
+ 0x93, 0x3E, 0x4D, 0x7E, 0x3C, 0x86 }; // http://msdn.microsoft.com/en-us/library/aa918757.aspx
+
+ di.dwSize = sizeof(di);
+
+ for( int i=0; ; i++)
+ {
+ if(0 == i)
+ { /* 1st time */
+ handle = FindFirstDevice( DeviceSearchByGuid, &guidCamera, &di );
+ if(!handle || !di.hDevice)
+ {
+ hr = ( HRESULT_FROM_WIN32( GetLastError() ));
+ goto bail;
+ }
+ }
+ else if(handle)
+ { /* 2nd or 3rd time */
+ BOOL ret = FindNextDevice(handle, &di);
+ if(!ret || !di.hDevice)
+ {
+ /* No 2nd or 3rd camera ==> do not return error*/
+ goto bail;
+ }
+ }
+ else assert(0);
+
+ StringCchCopy( pwzName, MAX_PATH, di.szDeviceName );
+
+ /* from LPWSTR to LPSTR */
+ char mbstr_name[MAX_PATH]; memset(mbstr_name,NULL,MAX_PATH);
+ wcstombs(mbstr_name, pwzName, MAX_PATH);
+
+ VideoGrabberName grabberName(std::string((const char*)mbstr_name), std::string((const char*)mbstr_name));
+ names->push_back(grabberName);
+ }
+
+bail:
+ /* close */
+ if(handle) FindClose( handle );
+
+#else
+ ICreateDevEnum *deviceEnum;
+ IEnumMoniker *enumerator;
+ IMoniker *moniker;
+
+ // Create the System Device Enumerator
+ hr = COCREATE(CLSID_SystemDeviceEnum, IID_ICreateDevEnum, deviceEnum);
+ if (FAILED(hr)) goto bail;
+
+ // Ask for a device enumerator
+ hr = deviceEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &enumerator, INCLUDE_CATEGORY_FLAG);
+ if (FAILED(hr)) goto bail;
+
+ // hr = S_FALSE and enumerator is NULL if there is no device to enumerate
+ if (!enumerator) goto bail;
+
+ USES_CONVERSION;
+
+ while (enumerator->Next(1, &moniker, NULL) == S_OK)
+ {
+ // Get the properties bag for each device
+ IPropertyBag *propBag;
+ hr = moniker->BindToStorage(0, 0, IID_IPropertyBag, reinterpret_cast<void**>(&propBag));
+ if (FAILED(hr))
+ {
+ SAFE_RELEASE(moniker);
+ continue;
+ }
+
+ std::string name;
+ std::string description;
+
+ VARIANT varName;
+ VariantInit(&varName);
+ VARIANT varDescription;
+ VariantInit(&varDescription);
+
+ // Find the device path (uniqueness is guaranteed)
+ hr = propBag->Read(L"DevicePath", &varName, 0);
+ if (SUCCEEDED(hr))
+ {
+ if (prefix != "") name = prefix + ":";
+ name = name + std::string(W2A(varName.bstrVal));
+ }
+
+ // Find friendly name or the description
+ hr = propBag->Read(L"FriendlyName", &varDescription, 0);
+ if (SUCCEEDED(hr))
+ {
+ description = std::string(W2A(varDescription.bstrVal));
+ }
+ else
+ {
+ hr = propBag->Read(L"Description", &varDescription, 0);
+ if (SUCCEEDED(hr)) description = std::string(W2A(varDescription.bstrVal));
+ }
+
+ hr = VariantClear(&varName);
+ hr = VariantClear(&varDescription);
+
+ SAFE_RELEASE(propBag);
+ SAFE_RELEASE(moniker);
+
+ // Add it to the list
+ if (name != "")
+ {
+ VideoGrabberName grabberName(name, description);
+ names->push_back(grabberName);
+ }
+ }
+
+bail:
+ SAFE_RELEASE(enumerator);
+ SAFE_RELEASE(deviceEnum);
+#endif
+
+ return hr;
+}
+
+HRESULT createSourceFilter(std::string *devicePath, IBaseFilter **sourceFilter)
+{
+ HRESULT hr;
+
+ IEnumMoniker *enumerator = NULL;
+ IMoniker *moniker = NULL;
+ bool found = false;
+
+ // Set sourceFilter to null
+ SAFE_RELEASE((*sourceFilter));
+
+#if defined( _WIN32_WCE)
+ CPropertyBag pBag;
+ HANDLE handle = NULL;
+ DEVMGR_DEVICE_INFORMATION di;
+ TCHAR pwzName[MAX_PATH];
+ CComVariant varCamName;
+ IPersistPropertyBag *propBag = NULL;
+ GUID guidCamera = { 0xCB998A05, 0x122C, 0x4166, 0x84, 0x6A,
+ 0x93, 0x3E, 0x4D, 0x7E, 0x3C, 0x86 }; // http://msdn.microsoft.com/en-us/library/aa918757.aspx
+
+ di.dwSize = sizeof(di);
+
+ for( int i=0; ; i++)
+ {
+ if(0 == i)
+ { /* 1st time */
+ handle = FindFirstDevice( DeviceSearchByGuid, &guidCamera, &di );
+ if(!handle || !di.hDevice)
+ {
+ hr = ( HRESULT_FROM_WIN32( GetLastError() ));
+ goto bail;
+ }
+ }
+ else if(handle)
+ { /* 2nd or 3rd time */
+ BOOL ret = FindNextDevice(handle, &di);
+ if(!ret || !di.hDevice)
+ {
+ /* No 2nd or 3rd camera ==> do not return error*/
+ goto bail;
+ }
+ }
+ else assert(0);
+
+ StringCchCopy( pwzName, MAX_PATH, di.szDeviceName );
+
+ /* from LPWSTR to LPSTR */
+ char mbstr_name[MAX_PATH];
+ memset(mbstr_name,NULL,MAX_PATH);
+ wcstombs(mbstr_name, pwzName, MAX_PATH);
+
+ if((std::string((const char*)mbstr_name) == (*devicePath)) || ("0" == (*devicePath)))
+ {
+ varCamName = pwzName;
+ if( varCamName.vt != VT_BSTR )
+ {
+ hr = E_OUTOFMEMORY;
+ goto bail;
+ }
+
+ // Create Source filter
+ hr = COCREATE(CLSID_VideoCapture, IID_IBaseFilter, *sourceFilter);
+ if(FAILED(hr)) goto bail;
+
+ // Query PropertyBag
+ hr = QUERY((*sourceFilter), IID_IPersistPropertyBag, propBag);
+ if(FAILED(hr)) goto bail;
+
+ hr = pBag.Write( L"VCapName", &varCamName );
+ if(FAILED(hr)) goto bail;
+
+ hr = propBag->Load( &pBag, NULL );
+ if(FAILED(hr)) goto bail;
+ }
+ }
+#else
+ ICreateDevEnum *deviceEnum = NULL;
+ IPropertyBag *propBag = NULL;
+
+ // Create the System Device Enumerator
+ hr = COCREATE(CLSID_SystemDeviceEnum, IID_ICreateDevEnum, deviceEnum);
+ if (FAILED(hr)){
+ goto bail;
+ }
+
+ // Ask for a device enumerator
+ hr = deviceEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &enumerator, INCLUDE_CATEGORY_FLAG);
+ if(FAILED(hr)){
+ goto bail;
+ }
+
+ // hr = S_FALSE and enumerator is NULL if there is no device to enumerate
+ if(!enumerator){
+ goto bail;
+ }
+
+ USES_CONVERSION;
+
+ while (!found && (enumerator->Next(1, &moniker, NULL) == S_OK)){
+ // Get the properties bag for each device
+ hr = moniker->BindToStorage(0, 0, IID_IPropertyBag, reinterpret_cast<void**>(&propBag));
+ if (FAILED(hr)){
+ SAFE_RELEASE(moniker);
+ continue;
+ }
+
+ std::string name;
+
+ VARIANT varName;
+ VariantInit(&varName);
+
+ // Find the device path (uniqueness is guaranteed)
+ hr = propBag->Read(L"DevicePath", &varName, 0);
+ if (SUCCEEDED(hr)) name = std::string(W2A(varName.bstrVal));
+
+ // Check for device path
+ // "Null" means first found
+ if ((name == (*devicePath)) ||
+ ("Null" == (*devicePath)))
+ {
+ hr = moniker->BindToObject(0, 0, IID_IBaseFilter, reinterpret_cast<void**>(&(*sourceFilter)));
+ if (SUCCEEDED(hr)){
+ (*devicePath) = name;
+ found = true;
+ }
+ }
+
+ hr = VariantClear(&varName);
+
+ SAFE_RELEASE(propBag);
+ SAFE_RELEASE(moniker);
+ }
+#endif
+
+bail:
+#ifdef _WIN32_WCE
+ if(handle) FindClose(handle);
+#else
+ SAFE_RELEASE(deviceEnum);
+#endif
+ SAFE_RELEASE(moniker);
+ SAFE_RELEASE(enumerator);
+ SAFE_RELEASE(propBag);
+
+ return hr;
+}
+
+HRESULT getSupportedFormats(IBaseFilter *sourceFilter, std::vector<DSCaptureFormat> *formats)
+{
+ HRESULT hr = E_FAIL;
+ IPin *pinOut = NULL;
+ IAMStreamConfig *streamConfig = NULL;
+ AM_MEDIA_TYPE *mediaType = NULL;
+ int count, size;
+
+ // Check source filter pointer
+ if (!sourceFilter) goto bail;
+
+ pinOut = GetPin(sourceFilter, PINDIR_OUTPUT);
+ if(!pinOut) goto bail;
+
+ // Retrieve the stream config interface
+ hr = QUERY(pinOut, IID_IAMStreamConfig, streamConfig);
+ if (FAILED(hr)) goto bail;
+
+ // Get the number of capabilities
+ hr = streamConfig->GetNumberOfCapabilities(&count, &size);
+ if (FAILED(hr)) goto bail;
+
+ hr = streamConfig->GetFormat(&mediaType);
+ if (FAILED(hr)) goto bail;
+
+ // Iterate through the formats
+ for (int i = 0; i < count; i++){
+ VIDEO_STREAM_CONFIG_CAPS streamConfigCaps;
+
+ hr = streamConfig->GetStreamCaps(i, &mediaType, reinterpret_cast<BYTE*>(&streamConfigCaps));
+
+ if (FAILED(hr)){
+ TSK_DEBUG_ERROR("Failed to get Stream caps");
+ break;
+ }
+
+ if (streamConfigCaps.guid == FORMAT_VideoInfo){
+ VIDEOINFOHEADER* vih = reinterpret_cast<VIDEOINFOHEADER*>(mediaType->pbFormat);
+ BITMAPINFOHEADER* bih = &vih->bmiHeader;
+
+ int width = abs(bih->biWidth);
+ int height = abs(bih->biHeight);
+ int fps = (int) ((float)(vih->AvgTimePerFrame)/10000.f);
+ GUID chroma = mediaType->subtype;
+
+ // Add format to the list
+ DSCaptureFormat format(width, height, fps, chroma);
+ formats->push_back(format);
+ }
+
+ DeleteMediaType(mediaType);
+ }
+
+bail:
+ SAFE_RELEASE(streamConfig);
+ SAFE_RELEASE(pinOut);
+
+ return hr;
+}
diff --git a/plugins/pluginDirectShow/internals/DSCaptureUtils.h b/plugins/pluginDirectShow/internals/DSCaptureUtils.h
new file mode 100644
index 0000000..7d99ed2
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSCaptureUtils.h
@@ -0,0 +1,60 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#ifndef PLUGIN_DSHOW_DSCAPTUREUTILS_H
+#define PLUGIN_DSHOW_DSCAPTUREUTILS_H
+
+#include "plugin_dshow_config.h"
+#include "internals/DSCaptureFormat.h"
+#include "internals/VideoGrabberName.h"
+
+#include <vector>
+
+// --------------------------------------------------------------------------------
+
+#ifdef INCLUDE_VFW_DEVICES
+#define INCLUDE_CATEGORY_FLAG 0
+#else
+#define INCLUDE_CATEGORY_FLAG CDEF_DEVMON_FILTER | CDEF_DEVMON_PNP_DEVICE
+#endif
+
+// --------------------------------------------------------------------------------
+
+/**
+* \brief Fills in a vector with VideoGrabberName instances constructed from the video capture devices.
+* \param A pointer to the device vector to append
+* \return An HRESULT value
+*/
+HRESULT enumerateCaptureDevices(const std::string &prefix, std::vector<VideoGrabberName> *names);
+
+/**
+* \brief Fills in a vector with VideoGrabberName instances constructed from the video capture devices.
+* \param A constant string containing a device path
+* \param A pointer to the filter that will contains the filter created or NULL if not the device is not found
+* \return An HRESULT value
+*/
+HRESULT createSourceFilter(std::string *devicePath, IBaseFilter **sourceFilter);
+
+/**
+* \brief Fills in a vector with DSCaptureFormat instances constructed from the given video capture device.
+* \param An instance of a capture device
+* \param A pointer to the format vector to append
+* \return An HRESULT value
+*/
+HRESULT getSupportedFormats(IBaseFilter *sourceFilter, std::vector<DSCaptureFormat> *formats);
+
+#endif
diff --git a/plugins/pluginDirectShow/internals/DSDibHelper.cxx b/plugins/pluginDirectShow/internals/DSDibHelper.cxx
new file mode 100644
index 0000000..b7f40d5
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSDibHelper.cxx
@@ -0,0 +1,80 @@
+#if !defined(_WIN32_WCE)
+//------------------------------------------------------------------------------
+// File: DibHelper.cpp
+//
+// Desc: DirectShow sample code - In-memory push mode source filter
+// Helper routines for manipulating bitmaps.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------------------------
+
+#include <windows.h>
+
+#include "dsdibhelper.h"
+
+
+HBITMAP CopyScreenToBitmap(LPRECT lpRect, BYTE *pData, BITMAPINFO *pHeader)
+{
+ HDC hScrDC, hMemDC; // screen DC and memory DC
+ HBITMAP hBitmap, hOldBitmap; // handles to deice-dependent bitmaps
+ int nX, nY, nX2, nY2; // coordinates of rectangle to grab
+ int nWidth, nHeight; // DIB width and height
+ int xScrn, yScrn; // screen resolution
+
+ // check for an empty rectangle
+ if (IsRectEmpty(lpRect))
+ return NULL;
+
+ // create a DC for the screen and create
+ // a memory DC compatible to screen DC
+ hScrDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
+ hMemDC = CreateCompatibleDC(hScrDC);
+
+ // get points of rectangle to grab
+ nX = lpRect->left;
+ nY = lpRect->top;
+ nX2 = lpRect->right;
+ nY2 = lpRect->bottom;
+
+ // get screen resolution
+ xScrn = GetDeviceCaps(hScrDC, HORZRES);
+ yScrn = GetDeviceCaps(hScrDC, VERTRES);
+
+ //make sure bitmap rectangle is visible
+ if (nX < 0)
+ nX = 0;
+ if (nY < 0)
+ nY = 0;
+ if (nX2 > xScrn)
+ nX2 = xScrn;
+ if (nY2 > yScrn)
+ nY2 = yScrn;
+
+ nWidth = nX2 - nX;
+ nHeight = nY2 - nY;
+
+ // create a bitmap compatible with the screen DC
+ hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight);
+
+ // select new bitmap into memory DC
+ hOldBitmap = (HBITMAP) SelectObject(hMemDC, hBitmap);
+
+ // bitblt screen DC to memory DC
+ BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY);
+
+ // select old bitmap back into memory DC and get handle to
+ // bitmap of the screen
+ hBitmap = (HBITMAP) SelectObject(hMemDC, hOldBitmap);
+
+ // Copy the bitmap data into the provided BYTE buffer
+ GetDIBits(hScrDC, hBitmap, 0, nHeight, pData, pHeader, DIB_RGB_COLORS);
+
+ // clean up
+ DeleteDC(hScrDC);
+ DeleteDC(hMemDC);
+
+ // return handle to the bitmap
+ return hBitmap;
+}
+
+#endif /* _WIN32_WCE */
diff --git a/plugins/pluginDirectShow/internals/DSDibHelper.h b/plugins/pluginDirectShow/internals/DSDibHelper.h
new file mode 100644
index 0000000..7b5481e
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSDibHelper.h
@@ -0,0 +1,106 @@
+//------------------------------------------------------------------------------
+// File: DibHelper.H
+//
+// Desc: DirectShow sample code - Helper code for bitmap manipulation
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------------------------
+
+#ifndef PLUGIN_DSHOW_DSDIBHELPER_H
+#define PLUGIN_DSHOW_DSDIBHELPER_H
+
+#define HDIB HANDLE
+
+/* DIB macros */
+#define IS_WIN30_DIB(lpbi) ((*(LPDWORD)(lpbi)) == sizeof(BITMAPINFOHEADER))
+#define RECTWIDTH(lpRect) ((lpRect)->right - (lpRect)->left)
+#define RECTHEIGHT(lpRect) ((lpRect)->bottom - (lpRect)->top)
+
+// Function prototypes
+HDIB BitmapToDIB (HBITMAP hBitmap, HPALETTE hPal);
+HDIB ChangeBitmapFormat (HBITMAP hBitmap,
+ WORD wBitCount,
+ DWORD dwCompression,
+ HPALETTE hPal);
+HDIB ChangeDIBFormat (HDIB hDIB, WORD wBitCount, DWORD dwCompression);
+
+HBITMAP CopyScreenToBitmap(LPRECT lpRect, BYTE *pData, BITMAPINFO *pHeader);
+HDIB CopyScreenToDIB (LPRECT);
+HBITMAP CopyWindowToBitmap (HWND, WORD);
+HDIB CopyWindowToDIB (HWND, WORD);
+
+HPALETTE CreateDIBPalette (HDIB);
+HDIB CreateDIB(DWORD, DWORD, WORD);
+WORD DestroyDIB (HDIB);
+
+void DIBError (int ErrNo);
+DWORD DIBHeight (LPSTR lpDIB);
+WORD DIBNumColors (LPSTR lpDIB);
+HBITMAP DIBToBitmap (HDIB hDIB, HPALETTE hPal);
+DWORD DIBWidth (LPSTR lpDIB);
+
+LPSTR FindDIBBits (LPSTR lpDIB);
+HPALETTE GetSystemPalette (void);
+HDIB LoadDIB (LPSTR);
+
+BOOL PaintBitmap (HDC, LPRECT, HBITMAP, LPRECT, HPALETTE);
+BOOL PaintDIB (HDC, LPRECT, HDIB, LPRECT, HPALETTE);
+
+int PalEntriesOnDevice (HDC hDC);
+WORD PaletteSize (LPSTR lpDIB);
+WORD SaveDIB (HDIB, LPSTR);
+
+#endif /* PLUGIN_DSHOW_DSDIBHELPER_H */
+//------------------------------------------------------------------------------
+// File: DibHelper.H
+//
+// Desc: DirectShow sample code - Helper code for bitmap manipulation
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------------------------
+
+#ifndef PLUGIN_DSHOW_DSDIBHELPER_H
+#define PLUGIN_DSHOW_DSDIBHELPER_H
+
+#define HDIB HANDLE
+
+/* DIB macros */
+#define IS_WIN30_DIB(lpbi) ((*(LPDWORD)(lpbi)) == sizeof(BITMAPINFOHEADER))
+#define RECTWIDTH(lpRect) ((lpRect)->right - (lpRect)->left)
+#define RECTHEIGHT(lpRect) ((lpRect)->bottom - (lpRect)->top)
+
+// Function prototypes
+HDIB BitmapToDIB (HBITMAP hBitmap, HPALETTE hPal);
+HDIB ChangeBitmapFormat (HBITMAP hBitmap,
+ WORD wBitCount,
+ DWORD dwCompression,
+ HPALETTE hPal);
+HDIB ChangeDIBFormat (HDIB hDIB, WORD wBitCount, DWORD dwCompression);
+
+HBITMAP CopyScreenToBitmap(LPRECT lpRect, BYTE *pData, BITMAPINFO *pHeader);
+HDIB CopyScreenToDIB (LPRECT);
+HBITMAP CopyWindowToBitmap (HWND, WORD);
+HDIB CopyWindowToDIB (HWND, WORD);
+
+HPALETTE CreateDIBPalette (HDIB);
+HDIB CreateDIB(DWORD, DWORD, WORD);
+WORD DestroyDIB (HDIB);
+
+void DIBError (int ErrNo);
+DWORD DIBHeight (LPSTR lpDIB);
+WORD DIBNumColors (LPSTR lpDIB);
+HBITMAP DIBToBitmap (HDIB hDIB, HPALETTE hPal);
+DWORD DIBWidth (LPSTR lpDIB);
+
+LPSTR FindDIBBits (LPSTR lpDIB);
+HPALETTE GetSystemPalette (void);
+HDIB LoadDIB (LPSTR);
+
+BOOL PaintBitmap (HDC, LPRECT, HBITMAP, LPRECT, HPALETTE);
+BOOL PaintDIB (HDC, LPRECT, HDIB, LPRECT, HPALETTE);
+
+int PalEntriesOnDevice (HDC hDC);
+WORD PaletteSize (LPSTR lpDIB);
+WORD SaveDIB (HDIB, LPSTR);
+
+#endif /* PLUGIN_DSHOW_DSDIBHELPER_H */ \ No newline at end of file
diff --git a/plugins/pluginDirectShow/internals/DSDisplay.cxx b/plugins/pluginDirectShow/internals/DSDisplay.cxx
new file mode 100644
index 0000000..326b86c
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSDisplay.cxx
@@ -0,0 +1,622 @@
+/*
+* Copyright (C) 2010-2011 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#include "internals/DSDisplay.h"
+#include "internals/DSUtils.h"
+
+#include "tsk_list.h"
+#include "tsk_debug.h"
+
+#include <string>
+
+using namespace std;
+
+#define USE_OVERLAY 0
+#define OVERLAY_TIMEOUT 3
+#define WM_GRAPHNOTIFY WM_APP + 1
+
+#define FSCREEN_MIN_IDEAL_WIDTH 352
+#define FSCREEN_MIN_IDEAL_HEIGHT 288
+
+typedef struct tdshow_display_s
+{
+ TSK_DECLARE_OBJECT;
+
+ HWND hwnd;
+ DSDisplay* display;
+}
+tdshow_display_t;
+typedef tsk_list_t tdshow_displays_L_t;
+const tsk_object_def_t *tdshow_display_def_t;
+
+// Static list to find which display is link to a given hWnd
+static tdshow_displays_L_t* __directshow__Displays = tsk_null;
+
+/*== Predicate function to find tdshow_display_t object by HWND. */
+static int __pred_find_display_by_hwnd(const tsk_list_item_t *item, const void *hWnd)
+{
+ if(item && item->data){
+ const tdshow_display_t *display = (const tdshow_display_t *)item->data;
+ int ret = 0;
+ tsk_subsat_int32_ptr(display->hwnd, *((HWND*)hWnd), &ret);
+ return ret;
+ }
+ return -1;
+}
+
+// C Callback that dispatch event to the right display
+static LRESULT CALLBACK __directshow__WndProcWindow(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ LRESULT result = FALSE;
+ BOOL resultSet = FALSE;
+
+ if(__directshow__Displays){
+ tsk_list_lock(__directshow__Displays);
+
+ const tdshow_display_t *display = (const tdshow_display_t *)tsk_list_find_object_by_pred(__directshow__Displays, __pred_find_display_by_hwnd, &hWnd);
+ if((resultSet = (display && display->display))){
+ result = display->display->handleEvents(hWnd, uMsg, wParam, lParam);
+ }
+
+ tsk_list_unlock(__directshow__Displays);
+ }
+
+ return resultSet ? result : DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+
+DSDisplay::DSDisplay(HRESULT *hr)
+{
+ this->window = NULL;
+ this->parentWindowProc = NULL;
+ this->hooked = false;
+ this->fullscreen = false;
+ this->bPluginFirefox = false;
+ this->top = 0;
+ this->left = 0;
+ this->width = this->imgWidth = 176;
+ this->height = this->imgHeight = 144;
+ this->fps = 15;
+
+ this->graph = new DSDisplayGraph(hr);
+ if (FAILED(*hr)) return;
+#if USE_OVERLAY
+ this->overlay = new DSDisplayOverlay();
+#else
+ this->overlay = NULL;
+#endif
+
+ this->graph->getVideoWindow()->put_Visible(OAFALSE);
+}
+
+DSDisplay::~DSDisplay()
+{
+ this->unhook();
+
+ SAFE_DELETE_PTR(this->overlay);
+ SAFE_DELETE_PTR(this->graph);
+}
+
+void DSDisplay::start()
+{
+ if (!this->graph->isRunning()){
+ this->hook();
+ }
+ if (!this->graph->isRunning() || this->graph->isPaused()){
+ this->graph->start();
+ }
+ this->graph->getVideoWindow()->put_Visible(OATRUE);
+}
+
+void DSDisplay::pause()
+{
+ this->graph->pause();
+}
+
+void DSDisplay::stop()
+{
+ if (this->graph->isRunning()){
+ this->setFullscreen(false);
+
+ this->graph->stop();
+ this->unhook();
+ }
+}
+
+void DSDisplay::attach(INT64 parent)
+{
+ this->attach((void*)parent);
+}
+
+void DSDisplay::attach(void *parent)
+{
+ // Don't reattach if this is the same parent
+ if (this->isAttached() && parent){
+ HWND hwnd = reinterpret_cast<HWND>(parent);
+ if (hwnd != this->window){
+ this->detach();
+ }
+ }
+
+ // Gets the handle of the parent
+ this->window = reinterpret_cast<HWND>(parent);
+ // Hook to the parent WindowProc
+ this->hook();
+
+#if USE_OVERLAY
+ // Allows the overlay to initialize
+ this->overlay->attach(this->window, this->graph);
+#endif
+}
+
+void DSDisplay::detach(void *parent)
+{
+ // The detach action is only valid and if this is the same parent
+ if (parent){
+ HWND hwnd = reinterpret_cast<HWND>(parent);
+ if (hwnd == this->window){
+ this->detach();
+ }
+ }
+}
+
+void DSDisplay::detach()
+{
+ if (!this->isAttached()){
+ return;
+ }
+
+#if USE_OVERLAY
+ // Clean up overlay
+ this->overlay->detach();
+#endif
+
+ // Unhook from the parent WindowProc
+ this->unhook();
+
+ // Set the handle of the parent to NULL
+ this->window = NULL;
+}
+
+bool DSDisplay::isAttached()
+{
+ return (this->window != NULL);
+}
+
+int DSDisplay::getWidth()
+{
+ return this->width;
+}
+
+int DSDisplay::getHeight()
+{
+ return this->height;
+}
+
+void DSDisplay::setSize(int w, int h)
+{
+ //this->width = w;
+ //this->height = h;
+
+ if (!this->fullscreen){
+ this->graph->setImageFormat(w, h);
+ if(this->hooked){
+#if 0
+ #if defined(VMR9_WINDOWLESS)
+ RECT rc;
+ SetRect(&rc, 0, 0, w, h);
+ this->graph->getWindowlessControl()->SetVideoPosition(&rc, &rc);
+ #else
+ this->graph->getVideoWindow()->SetWindowPosition(0, 0, this->width , this->height);
+ #endif
+#endif
+ }
+ }
+}
+
+void DSDisplay::applyRatio(RECT rect)
+{
+ long w = rect.right - rect.left;
+ long h = rect.bottom - rect.top;
+ float ratio = ((float)this->imgWidth/(float)this->imgHeight);
+ // (w/h)=ratio =>
+ // 1) h=w/ratio
+ // and
+ // 2) w=h*ratio
+ this->width = (int)(w/ratio) > h ? (int)(h * ratio) : w;
+ this->height = (int)(this->width/ratio) > h ? h : (int)(this->width/ratio);
+ this->left = ((w - this->width) >> 1);
+ this->top = ((h - this->height) >> 1);
+}
+
+bool DSDisplay::isFullscreen()
+{
+#if defined(VMR9_WINDOWLESS)
+ // TODO
+#else
+ long result;
+ HRESULT hr = this->graph->getVideoWindow()->get_FullScreenMode(&result);
+ if (SUCCEEDED(hr)){
+ this->fullscreen = (result == OATRUE);
+ }
+ else{
+ TSK_DEBUG_ERROR("get_FullScreenMode failed with %ld", hr);
+ this->fullscreen = FALSE;
+ }
+#endif
+ return this->fullscreen;
+}
+
+void DSDisplay::setFullscreen(bool value)
+{
+ if(!this->canFullscreen()){
+ TSK_DEBUG_WARN("Cannot fullscreen");
+ return;
+ }
+
+ HRESULT hr;
+
+#if defined(VMR9_WINDOWLESS)
+ // TODO
+#else
+ if (this->isFullscreen() == value){
+ return;
+ }
+
+ hr = this->graph->getVideoWindow()->put_FullScreenMode(value ? OATRUE : OAFALSE);
+ if (SUCCEEDED(hr)){
+ this->fullscreen = value;
+#if USE_OVERLAY
+ this->overlay->show(this->fullscreen ? (OVERLAY_TIMEOUT * this->graph->getDisplayFps()) : 0);
+#endif
+ }
+ else{
+ TSK_DEBUG_ERROR("put_FullScreenMode failed with %ld", hr);
+ }
+#endif
+}
+
+void DSDisplay::setPluginFirefox(bool value)
+{
+ bPluginFirefox = value;
+}
+
+bool DSDisplay::canFullscreen()
+{
+#if defined(VMR9_WINDOWLESS)
+ // TODO
+#else
+ if(this->graph){
+ UINT image_w, image_h;
+
+ if( this->graph->getImageFormat(image_w, image_h) ){
+ //this->graph->getVideoWindow()->GetMinIdealImageSize(&ideal_w, &ideal_h);
+ return (((long)image_w >= FSCREEN_MIN_IDEAL_WIDTH) && ((long)image_h >= FSCREEN_MIN_IDEAL_HEIGHT));
+ }
+ }
+#endif
+ return false;
+}
+
+void DSDisplay::setFps(int fps_)
+{
+ this->fps = fps_;
+ this->graph->setDisplayFps(fps_);
+}
+
+
+// w and h are the size of the buffer not the display
+void DSDisplay::handleVideoFrame(const void* data, int w, int h)
+{
+ if (this->graph->isRunning()){
+ // The graph will take care of changing the source filter if needed
+ // in case of dimension change or anything else...
+ this->graph->handleFrame(data, w, h);
+ if(this->imgWidth != w || this->imgHeight != h){
+ this->imgWidth = w;
+ this->imgHeight = h;
+ if(this->window){
+ SendMessage(this->window, WM_SIZE, SIZE_RESTORED, MAKELPARAM(this->width , this->height));
+ }
+ }
+#if USE_OVERLAY
+ this->overlay->update();
+#endif
+ }
+}
+
+LRESULT DSDisplay::handleEvents(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg)
+ {
+ case WM_CREATE:
+ case WM_SIZE:
+ case WM_MOVE:
+ {
+ RECT rect = {0};
+ GetWindowRect(hWnd, &rect);
+ applyRatio(rect);
+
+#if defined(VMR9_WINDOWLESS)
+ this->graph->getWindowlessControl()->SetVideoPosition(&rect, &rect);
+#else
+ this->graph->getVideoWindow()->SetWindowPosition(this->left, this->top, this->width , this->height);
+#endif
+ }
+ break;
+
+ case WM_LBUTTONDBLCLK:
+ if(this->canFullscreen()){
+ this->setFullscreen(true);
+ }
+ break;
+
+ case WM_FULLSCREEN_SET:
+ if(this->canFullscreen()){
+ this->setFullscreen(!this->isFullscreen());
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_KEYDOWN:
+ if(this->isFullscreen())
+ {
+#if USE_OVERLAY
+ // Re-Show overlay
+ this->overlay->show(OVERLAY_TIMEOUT * this->graph->getDisplayFps());
+#endif
+ }
+ break;
+
+ case WM_CHAR:
+ case WM_KEYUP:
+ if(this->isFullscreen() && (wParam == 0x1B || wParam == VK_ESCAPE))
+ {
+ // escape
+ this->setFullscreen(false);
+ }
+
+ break;
+
+ case WM_GRAPHNOTIFY:
+ {
+ long evCode;
+ LONG_PTR param1, param2;
+ HRESULT hr;
+ while (hr = this->graph->getMediaEvent()->GetEvent(&evCode, &param1, &param2, 0), SUCCEEDED(hr))
+ {
+ hr = this->graph->getMediaEvent()->FreeEventParams(evCode, param1, param2);
+
+ switch(evCode)
+ {
+ case EC_FULLSCREEN_LOST:
+#if USE_OVERLAY
+ this->overlay->show(0);
+#endif
+ break;
+ case EC_COMPLETE:
+ case EC_USERABORT:
+ default:
+ break;
+ }
+ }
+ }
+ break;
+
+#if defined(VMR9_WINDOWLESS)
+ case WM_DISPLAYCHANGE:
+ {
+ this->graph->getWindowlessControl()->DisplayModeChanged();
+ }
+ break;
+ case WM_PAINT:
+ {
+ RECT rect = {0};
+ GetWindowRect(hWnd, &rect);
+
+ PAINTSTRUCT ps;
+ HDC hdc = BeginPaint(hWnd, &ps);
+
+ this->graph->getWindowlessControl()->RepaintVideo(hWnd, hdc);
+
+ EndPaint(hWnd, &ps);
+ }
+ break;
+#endif
+
+ }
+
+ return bPluginFirefox ? DefWindowProc(hWnd, uMsg, wParam, lParam) : CallWindowProc(this->parentWindowProc, hWnd, uMsg, wParam, lParam);
+}
+
+void DSDisplay::hook()
+{
+ HRESULT hr;
+
+ if (!this->window){
+ return;
+ }
+
+ if(this->hooked){
+ return;
+ }
+ this->hooked = TRUE;
+
+ bool lock = (__directshow__Displays != NULL);
+
+ if(lock)
+ tsk_list_lock(__directshow__Displays);
+ {
+ // Gets the parent Window procedure
+#if defined(_WIN32_WCE)
+ // Workaround for bug in SetWindowLong, call twice the API
+ //this->parentWindowProc = (WNDPROC)SetWindowLong( this->window, GWL_WNDPROC, (LONG) __directshow__WndProcWindow );
+ //this->parentWindowProc = (WNDPROC)SetWindowLong( this->window, GWL_WNDPROC, (LONG) __directshow__WndProcWindow );
+ //__directshow__Displays[this->window] = this;
+#else
+ this->parentWindowProc = (WNDPROC) SetWindowLongPtr(this->window, GWLP_WNDPROC, (LONG_PTR) __directshow__WndProcWindow);
+ // Add this instance to the callback map
+ tsk_object_new(tdshow_display_def_t, this->window, this);
+#endif
+ }
+ if(lock)
+ tsk_list_unlock(__directshow__Displays);
+
+ RECT rect;
+ GetWindowRect(this->window, &rect);
+ applyRatio(rect);
+
+#if defined(VMR9_WINDOWLESS)
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = this->width;
+ rect.bottom = this->height;
+
+ // TODO : Review
+ hr = this->graph->getWindowlessControl()->SetVideoClippingWindow(this->window);
+ hr = this->graph->getWindowlessControl()->SetBorderColor(RGB(0, 0, 128));
+ hr = this->graph->getWindowlessControl()->SetVideoPosition(NULL, &rect);
+#else
+ // TODO : Review the order
+ hr = this->graph->getVideoWindow()->put_Owner((OAHWND) this->window);
+ hr = this->graph->getVideoWindow()->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
+ hr = this->graph->getVideoWindow()->SetWindowPosition(this->left, this->top, this->width, this->height);
+ hr = this->graph->getVideoWindow()->put_MessageDrain((OAHWND) this->window);
+ hr = this->graph->getVideoWindow()->put_Visible(OATRUE);
+#endif
+
+ hr = this->graph->getMediaEvent()->SetNotifyWindow((OAHWND) this->window, WM_GRAPHNOTIFY, 0);
+}
+
+void DSDisplay::unhook()
+{
+ HRESULT hr;
+
+ if(!this->window){
+ return;
+ }
+
+ if(!this->hooked){
+ return;
+ }
+
+ hr = this->graph->getMediaEvent()->SetNotifyWindow(NULL, WM_GRAPHNOTIFY, 0);
+
+#if defined(VMR9_WINDOWLESS)
+ // TODO : Review
+ hr = this->graph->getWindowlessControl()->SetVideoClippingWindow(NULL);
+#else
+ // TODO : Review the order
+ hr = this->graph->getVideoWindow()->put_Visible(OAFALSE);
+ hr = this->graph->getVideoWindow()->put_MessageDrain((OAHWND) NULL);
+ hr = this->graph->getVideoWindow()->put_Owner((OAHWND) NULL);
+ hr = this->graph->getVideoWindow()->put_AutoShow(OAFALSE);
+#endif
+
+ bool lock = (__directshow__Displays != NULL);
+ if(lock)
+ tsk_list_lock(__directshow__Displays);
+ {
+ // Remove this instance from the callback map
+ tsk_list_remove_item_by_pred(__directshow__Displays, __pred_find_display_by_hwnd, &this->window);
+ // Restore parent Window procedure
+#if defined(_WIN32_WCE)
+ // Workaround for bug in SetWindowLong, call twice the API
+ //this->parentWindowProc = (WNDPROC)SetWindowLong( this->window, GWL_WNDPROC, (LONG) this->parentWindowProc );
+ //this->parentWindowProc = (WNDPROC)SetWindowLong( this->window, GWL_WNDPROC, (LONG) this->parentWindowProc );
+#else
+ SetWindowLongPtr(this->window, GWLP_WNDPROC, (LONG_PTR) this->parentWindowProc);
+#endif
+ }
+ if(lock)
+ tsk_list_unlock(__directshow__Displays);
+
+ this->hooked = FALSE;
+}
+
+
+
+
+
+
+
+
+
+
+
+//=================================================================================================
+// String object definition
+//
+static tsk_object_t* tdshow_display_ctor(tsk_object_t * self, va_list * app)
+{
+ tdshow_display_t *display = (tdshow_display_t *)self;
+
+ if(display){
+ display->hwnd = va_arg(*app, HWND);
+ display->display = va_arg(*app, DSDisplay*);
+
+ if(!__directshow__Displays){
+ __directshow__Displays = tsk_list_create();
+ }
+ tsk_list_push_back_data(__directshow__Displays, (void**)&display);
+ }
+
+ return self;
+}
+
+static tsk_object_t* tdshow_display_dtor(tsk_object_t * self)
+{
+ tdshow_display_t *display = (tdshow_display_t *)self;
+ if(display){
+ if(__directshow__Displays){
+ tsk_list_remove_item_by_data(__directshow__Displays, display);
+ //if(TSK_LIST_IS_EMPTY(__directshow__Displays)){
+ // TSK_OBJECT_SAFE_FREE(__directshow__Displays);
+ //}
+ }
+ }
+
+ return self;
+}
+
+static int tdshow_display_cmp(const tsk_object_t *_d1, const tsk_object_t *_d2)
+{
+ const tdshow_display_t *d1 = (const tdshow_display_t *)_d1;
+ const tdshow_display_t *d2 = (const tdshow_display_t *)_d2;
+
+ if(d1 && d2){
+ int ret = 0;
+ tsk_subsat_int32_ptr(d1->hwnd, d2->hwnd, &ret);
+ return ret;
+ }
+ else if(!d1 && !d2) return 0;
+ else return -1;
+}
+
+static const tsk_object_def_t tdshow_display_def_s =
+{
+ sizeof(tdshow_display_t),
+ tdshow_display_ctor,
+ tdshow_display_dtor,
+ tdshow_display_cmp,
+};
+extern const tsk_object_def_t *tdshow_display_def_t = &tdshow_display_def_s;
diff --git a/plugins/pluginDirectShow/internals/DSDisplay.h b/plugins/pluginDirectShow/internals/DSDisplay.h
new file mode 100644
index 0000000..b2985ef
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSDisplay.h
@@ -0,0 +1,84 @@
+/*
+* Copyright (C) 2010-2011 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef PLUGIN_DSHOW_DIRECTSHOW_DISPLAY_H
+#define PLUGIN_DSHOW_DIRECTSHOW_DISPLAY_H
+
+#include "plugin_dshow_config.h"
+
+#include "internals/DSDisplayGraph.h"
+#include "internals/DSDisplayOverlay.h"
+
+#define WM_FULLSCREEN_SET (WM_USER + 401)
+
+class DSDisplay
+{
+public:
+ DSDisplay(HRESULT *hr);
+ virtual ~DSDisplay();
+
+ virtual void attach(INT64 parent);
+ virtual void attach(void *parent);
+ virtual void detach(void *parent);
+ virtual void detach();
+ virtual bool isAttached();
+
+ virtual void start();
+ virtual void pause();
+ virtual void stop();
+
+ virtual int getWidth();
+ virtual int getHeight();
+ virtual void setSize(int w, int h);
+
+ virtual bool isFullscreen();
+ virtual void setFullscreen(bool value);
+ virtual void setPluginFirefox(bool value);
+
+ virtual bool canFullscreen();
+
+ virtual void setFps(int fps_);
+
+ virtual void handleVideoFrame(const void* data, int w, int h);
+
+ LRESULT handleEvents(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+private:
+ void hook();
+ void unhook();
+ void applyRatio(RECT rect);
+
+private:
+ DSDisplayGraph *graph;
+ DSDisplayOverlay *overlay;
+
+ int fps;
+ int left, top, width, height, imgWidth, imgHeight;
+
+ bool bPluginFirefox;
+ bool fullscreen;
+ HWND window;
+ WNDPROC parentWindowProc;
+
+ bool hooked;
+};
+
+#endif
diff --git a/plugins/pluginDirectShow/internals/DSDisplayGraph.cxx b/plugins/pluginDirectShow/internals/DSDisplayGraph.cxx
new file mode 100644
index 0000000..b2da43b
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSDisplayGraph.cxx
@@ -0,0 +1,345 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#if defined(VMR9)
+#define DIRECT3D_VERSION 0x0900
+#endif
+
+#include "internals/DSDisplayGraph.h"
+#include "internals/DSUtils.h"
+#include "internals/DSOutputFilter.h"
+
+#include "tsk_debug.h"
+
+#include <iostream>
+
+using namespace std;
+
+DSDisplayGraph::DSDisplayGraph(HRESULT *hr)
+{
+ this->running = FALSE;
+ this->paused = FALSE;
+ this->fps = 15;
+
+ this->graphBuilder = NULL;
+
+ this->sourceFilter = NULL;
+ this->colorspaceConverterFilter = NULL;
+ this->videoRendererFilter = NULL;
+
+ this->mediaController = NULL;
+ this->mediaEvent = NULL;
+ this->videoWindow = NULL;
+
+#if defined(VMR) ||defined(VMR9) || defined(VMR9_WINDOWLESS)
+ this->mixerBitmap = NULL;
+ this->filterConfig = NULL;
+#endif
+
+#if defined(VMR9_WINDOWLESS)
+ this->windowlessControl = NULL;
+#endif
+
+ *hr = this->createDisplayGraph();
+ if (FAILED(*hr)) return;
+
+ *hr = this->connect();
+ if (FAILED(*hr)) return;
+}
+
+DSDisplayGraph::~DSDisplayGraph()
+{
+ this->disconnect();
+
+#if defined(VMR9_WINDOWLESS)
+ SAFE_RELEASE(this->windowlessControl);
+#endif
+
+#if defined(VMR) ||defined(VMR9) || defined(VMR9_WINDOWLESS)
+ SAFE_RELEASE(this->filterConfig);
+ SAFE_RELEASE(this->mixerBitmap);
+#endif
+
+ SAFE_RELEASE(this->videoWindow);
+ SAFE_RELEASE(this->mediaEvent);
+ SAFE_RELEASE(this->mediaController);
+
+ SAFE_RELEASE(this->colorspaceConverterFilter);
+ SAFE_RELEASE(this->videoRendererFilter);
+ //SAFE_RELEASE(this->sourceFilter);
+
+ SAFE_RELEASE(this->graphBuilder);
+}
+
+void DSDisplayGraph::setDisplayFps(int fps_)
+{
+ this->fps = fps_;
+ if(this->sourceFilter){
+ this->sourceFilter->setFps(fps_);
+ }
+}
+
+bool DSDisplayGraph::getImageFormat(UINT &width, UINT &height)
+{
+ if(this->sourceFilter){
+ return this->sourceFilter->getImageFormat(width, height);
+ }
+ return false;
+}
+
+bool DSDisplayGraph::setImageFormat(UINT width, UINT height)
+{
+ bool ret = true;
+ if(this->sourceFilter){
+ UINT w=width, h = height;
+ if(this->sourceFilter->getImageFormat(w, h)){
+ if(w!= width || h!=height){ // Image format has changed
+ bool reconnect = this->connected; // IMPORTANT: Must reconnect all elements
+ HRESULT hr;
+ if(reconnect){
+ if((hr = this->disconnect()) != S_OK){
+ return false;
+ }
+ }
+ ret = (this->sourceFilter->setImageFormat(width, height) == S_OK);
+ if(reconnect){
+ if((hr = this->connect())){
+ return false;
+ }
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+HRESULT DSDisplayGraph::connect()
+{
+ HRESULT hr;
+
+ if((hr = ConnectFilters(this->graphBuilder, this->sourceFilter, this->colorspaceConverterFilter)) != S_OK){
+ TSK_DEBUG_ERROR("Failed to connect sourcefilter with the colorspace");
+ return hr;
+ }
+ if((hr = ConnectFilters(this->graphBuilder, this->colorspaceConverterFilter, this->videoRendererFilter)) != S_OK){
+ TSK_DEBUG_ERROR("Failed to connect colorspace with the videorenderer");
+ return hr;
+ }
+
+ this->connected = true;
+ return S_OK;
+}
+
+HRESULT DSDisplayGraph::disconnect()
+{
+ HRESULT hr;
+
+ if((hr = DisconnectFilters(this->graphBuilder, this->sourceFilter, this->colorspaceConverterFilter)) != S_OK){
+ TSK_DEBUG_ERROR("Failed to disconnect sourcefilter with the colorspace");
+ return hr;
+ }
+ if((hr = DisconnectFilters(this->graphBuilder, this->colorspaceConverterFilter, this->videoRendererFilter)) != S_OK){
+ TSK_DEBUG_ERROR("Failed to connect colorspace with the videorenderer");
+ return hr;
+ }
+
+ this->connected = false;
+ return S_OK;
+}
+
+HRESULT DSDisplayGraph::start()
+{
+ HRESULT hr;
+ this->running = true;
+ this->sourceFilter->reset();
+
+ hr = this->mediaController->Run();
+ if (!SUCCEEDED(hr)){
+ TSK_DEBUG_ERROR("DSDisplayGraph::mediaController->Run() has failed with %ld", hr);
+ }
+ return hr;
+}
+
+HRESULT DSDisplayGraph::pause()
+{
+ HRESULT hr = S_OK;
+ if(isRunning() && !isPaused()){
+ hr = this->mediaController->Pause();
+ if(SUCCEEDED(hr)){
+ this->paused = true;
+ }
+ }
+ return hr;
+}
+
+HRESULT DSDisplayGraph::stop()
+{
+ HRESULT hr;
+
+ hr = this->mediaController->Pause();
+ if (hr == S_FALSE){
+ TSK_DEBUG_ERROR("DSDisplayGraph::mediaController->Pause() has failed with %ld. Waiting for transition.", hr);
+ FILTER_STATE pfs;
+ hr = this->mediaController->GetState(2500, (OAFilterState*) &pfs);
+ }
+
+ hr = this->mediaController->Stop();
+ if (!SUCCEEDED(hr)){
+ TSK_DEBUG_ERROR("DSDisplayGraph::mediaController->Stop() has failed with %ld", hr);
+ }
+
+ this->running = false;
+ this->paused = false;
+
+ return hr;
+}
+
+bool DSDisplayGraph::isRunning()
+{
+ return this->running;
+}
+
+bool DSDisplayGraph::isPaused()
+{
+ return this->paused;
+}
+
+void DSDisplayGraph::handleFrame(const void* data, int w, int h)
+{
+ HRESULT hr;
+
+ if(!this->sourceFilter){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return;
+ }
+
+ if(!data || !this->running){
+ this->sourceFilter->setBuffer(NULL, (w*h*3));
+ return;
+ }
+
+ hr = this->sourceFilter->setImageFormat(w, h);
+ if (hr == S_OK){
+ this->stop();
+
+ this->disconnect();
+ this->connect();
+
+ this->start();
+ }
+
+ this->sourceFilter->setBuffer((void*)data, (w*h*3));
+}
+
+HRESULT DSDisplayGraph::createDisplayGraph()
+{
+ HRESULT hr;
+
+ // Create the graph builder
+ hr = COCREATE(CLSID_FilterGraph, IID_IGraphBuilder, this->graphBuilder);
+ if(FAILED(hr)) return hr;
+
+
+ // Create my custom filter
+ LPUNKNOWN pUnk = NULL;
+ this->sourceFilter = new DSOutputFilter(pUnk, &hr /*, this*/);
+ if(FAILED(hr) || this->sourceFilter == NULL) return hr;
+
+ // Create the color space convertor filter
+ hr = COCREATE(CLSID_Colour, IID_IBaseFilter, this->colorspaceConverterFilter);
+ if(FAILED(hr)) return hr;
+
+#if defined(VMR)
+ // Create the video mixing renderer based on Direct X
+ hr = COCREATE(CLSID_VideoMixingRenderer, IID_IBaseFilter, this->videoRendererFilter);
+ if(FAILED(hr)) return hr;
+#elif defined(VMR9) || defined(VMR9_WINDOWLESS)
+ // Create the video mixing renderer based on Direct X 9.0
+ hr = COCREATE(CLSID_VideoMixingRenderer9, IID_IBaseFilter, this->videoRendererFilter);
+ if(FAILED(hr)) return hr;
+#else
+ // Create the video renderer
+ hr = COCREATE(CLSID_VideoRenderer, IID_IBaseFilter, this->videoRendererFilter);
+ if(FAILED(hr)) return hr;
+#endif
+
+
+ // Add dource filter to the graph
+ hr = this->graphBuilder->AddFilter(this->sourceFilter, FILTER_OUTPUT);
+ if(FAILED(hr)) return hr;
+
+ // Add the color space convertor to the graph
+ hr = this->graphBuilder->AddFilter(this->colorspaceConverterFilter, FILTER_COLORSPACE_CONVERTOR);
+ if(FAILED(hr)) return hr;
+
+ // Add video renderer to the graph
+ hr = this->graphBuilder->AddFilter(this->videoRendererFilter, FILTER_VIDEO_RENDERER);
+ if(FAILED(hr)) return hr;
+
+
+ // Find media control
+ hr = QUERY(this->graphBuilder, IID_IMediaControl, this->mediaController);
+ if(FAILED(hr)) return hr;
+
+ // Find media event
+ hr = QUERY(this->graphBuilder, IID_IMediaEventEx, this->mediaEvent);
+ if(FAILED(hr)) return hr;
+ // hr = this->mediaEvent->SetNotifyFlags(AM_MEDIAEVENT_NONOTIFY);
+
+
+#if defined(VMR)
+ // Find the bitmap mixer (Direct X)
+ hr = QUERY(this->videoRendererFilter, IID_IVMRMixerBitmap, this->mixerBitmap);
+ if(FAILED(hr)) return hr;
+
+ // Find the bitmap configurer (Direct X)
+ hr = QUERY(this->videoRendererFilter, IID_IVMRFilterConfig, this->filterConfig);
+ if(FAILED(hr)) return hr;
+
+ // Set the number of streams (Direct X)
+ hr = this->filterConfig->SetNumberOfStreams(1);
+ if(FAILED(hr)) return hr;
+#elif defined(VMR9) || defined(VMR9_WINDOWLESS)
+ // Find the bitmap mixer (Direct X 9.0)
+ hr = QUERY(this->videoRendererFilter, IID_IVMRMixerBitmap9, this->mixerBitmap);
+ if(FAILED(hr)) return hr;
+
+ // Find the bitmap configurer (Direct X 9.0)
+ hr = QUERY(this->videoRendererFilter, IID_IVMRFilterConfig9, this->filterConfig);
+ if(FAILED(hr)) return hr;
+
+ // Set the number of streams (Direct X 9.0)
+ hr = this->filterConfig->SetNumberOfStreams(1);
+ if(FAILED(hr)) return hr;
+#endif
+
+#if defined(VMR9_WINDOWLESS)
+ // Set the rendering mode (Direct X 9.0)
+ hr = this->filterConfig->SetRenderingMode(VMR9Mode_Windowless);
+ if(FAILED(hr)) return hr;
+
+ // Find the windowless control (Direct X 9.0)
+ hr = QUERY(this->videoRendererFilter, IID_IVMRWindowlessControl9, this->windowlessControl);
+ if(FAILED(hr)) return hr;
+#else
+ // Find IVideoWindow interface
+ hr = QUERY(this->graphBuilder, IID_IVideoWindow, this->videoWindow);
+ if(FAILED(hr)) return hr;
+#endif
+
+ return hr;
+}
diff --git a/plugins/pluginDirectShow/internals/DSDisplayGraph.h b/plugins/pluginDirectShow/internals/DSDisplayGraph.h
new file mode 100644
index 0000000..c9080fe
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSDisplayGraph.h
@@ -0,0 +1,110 @@
+/*
+* Copyright (C) 2010-2011 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef PLUGIN_DSHOW_DSDISPLAYGRAPH_H
+#define PLUGIN_DSHOW_DSDISPLAYGRAPH_H
+
+#include "plugin_dshow_config.h"
+
+#include <control.h>
+
+#include "internals/VideoFrame.h"
+#include "internals/DSOutputFilter.h"
+#include "internals/DSDisplayOverlay.h"
+
+#if defined(VMR9) || defined(VMR9_WINDOWLESS)
+#include <D3D9.h>
+#include <vmr9.h>
+#endif
+
+
+class DSDisplayGraph
+{
+public:
+ DSDisplayGraph(HRESULT *hr);
+ virtual ~DSDisplayGraph();
+
+ int getDisplayFps() { return this->fps; };
+ void setDisplayFps(int fps_);
+
+ bool getImageFormat(UINT &width, UINT &height);
+ bool setImageFormat(UINT width, UINT height);
+
+ HRESULT connect();
+ HRESULT disconnect();
+
+ HRESULT start();
+ HRESULT pause();
+ HRESULT stop();
+ bool isRunning();
+ bool isPaused();
+
+ IMediaEventEx *getMediaEvent() { return this->mediaEvent; };
+ IVideoWindow *getVideoWindow() { return this->videoWindow; };
+ DSOutputFilter *getSourceFilter() { return this->sourceFilter; };
+
+#if defined(VMR)
+ IVMRMixerBitmap *getMixerBitmap() { return this->mixerBitmap; };
+#elif defined(VMR9)
+ IVMRMixerBitmap9 *getMixerBitmap() { return this->mixerBitmap; };
+#elif defined(VMR9_WINDOWLESS)
+ IVMRMixerBitmap9 *getMixerBitmap() { return this->mixerBitmap; };
+ IVMRMixerControl9 *getMixerControl() { return this->mixerControl; };
+ IVMRWindowlessControl9 *getWindowlessControl() { return this->windowlessControl; };
+#endif
+
+ void handleFrame(const void* data, int w, int h);
+
+private:
+ HRESULT createDisplayGraph();
+
+private:
+ IGraphBuilder *graphBuilder;
+
+ DSOutputFilter *sourceFilter;
+ IBaseFilter *colorspaceConverterFilter;
+ IBaseFilter *videoRendererFilter;
+
+ IMediaControl *mediaController;
+ IMediaEventEx *mediaEvent;
+ IVideoWindow *videoWindow;
+
+#if defined(VMR)
+ IVMRMixerBitmap *mixerBitmap;
+ IVMRFilterConfig *filterConfig;
+#elif defined(VMR9)
+ IVMRMixerBitmap9 *mixerBitmap;
+ IVMRMixerControl9 *mixerControl;
+ IVMRFilterConfig9 *filterConfig;
+#elif defined(VMR9_WINDOWLESS)
+ IVMRMixerBitmap9 *mixerBitmap;
+ IVMRMixerControl9 *mixerControl;
+ IVMRFilterConfig9 *filterConfig;
+ IVMRWindowlessControl9 *windowlessControl;
+#endif
+
+ bool connected;
+ bool running;
+ bool paused;
+ int fps;
+};
+
+#endif
diff --git a/plugins/pluginDirectShow/internals/DSDisplayOverlay.VMR.cxx b/plugins/pluginDirectShow/internals/DSDisplayOverlay.VMR.cxx
new file mode 100644
index 0000000..dacea84
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSDisplayOverlay.VMR.cxx
@@ -0,0 +1,179 @@
+/*
+* Copyright (C) 2010-2011 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#if defined(VMR)
+
+#include "internals/DSDisplayOverlay.h"
+#include "internals/DSDisplayGraph.h"
+#include "internals/DSUtils.h"
+#include "../../resource.h"
+
+using namespace std;
+
+#define ALPHA_VALUE_START 0.8f
+#define ALPHA_VALUE_STOP 0.0f
+
+
+// Hack to get module of the current code
+// Only works with Microsoft Linker and could break in the future
+EXTERN_C IMAGE_DOS_HEADER __ImageBase;
+
+
+DSDisplayOverlay::DSDisplayOverlay()
+{
+ this->window = NULL;
+ this->hdcBmp = NULL;
+ this->hbmOld = NULL;
+}
+
+DSDisplayOverlay::~DSDisplayOverlay()
+{
+}
+
+void DSDisplayOverlay::attach(HWND parent, DSDisplayGraph *graph)
+{
+ HRESULT hr;
+
+ // Gets the handle of the parent and the graph
+ this->window = parent;
+ this->displayGraph = graph;
+
+ if (this->window)
+ {
+ // Hack to get module of the current code
+ TCHAR *modulePath = (TCHAR *) calloc(255, sizeof(TCHAR));
+ GetModuleFileName((HINSTANCE)&__ImageBase, modulePath, 255);
+ HMODULE module = GetModuleHandle(modulePath);
+ delete[] modulePath;
+ if (!module)
+ {
+ cout << "Failed to get current module";
+ return;
+ }
+
+ HBITMAP bitmap = LoadBitmap(module, MAKEINTRESOURCE(IDB_BITMAP_OVERLAY));
+ if (!bitmap)
+ {
+ cout << "Failed to load overlay bitmap" << endl;
+ return;
+ }
+
+ RECT rect;
+ hr = GetWindowRect(this->window, &rect);
+ if (FAILED(hr))
+ {
+ cout << "Failed to get window size" << endl;
+ return;
+ }
+
+ BITMAP bm;
+ HDC hdc = GetDC(this->window);
+ this->hdcBmp = CreateCompatibleDC(hdc);
+ ReleaseDC(this->window, hdc);
+
+ GetObject(bitmap, sizeof(bm), &bm);
+ this->hbmOld= (HBITMAP) SelectObject(this->hdcBmp, bitmap);
+
+ ZeroMemory(&this->alphaBitmap, sizeof(VMRALPHABITMAP));
+ this->alphaBitmap.dwFlags = VMRBITMAP_HDC | VMRBITMAP_SRCCOLORKEY;
+ this->alphaBitmap.hdc = this->hdcBmp;
+ this->alphaBitmap.clrSrcKey = 0x00FF00FF;
+ // Source rectangle
+ this->alphaBitmap.rSrc.left = 0;
+ this->alphaBitmap.rSrc.top = 0;
+ this->alphaBitmap.rSrc.right = bm.bmWidth;
+ this->alphaBitmap.rSrc.bottom = bm.bmHeight;
+ // Destination rectangle
+ this->alphaBitmap.rDest.left = (rect.right - rect.left - bm.bmWidth) / 2.0;
+ this->alphaBitmap.rDest.top = (rect.bottom - rect.top - bm.bmHeight) / 2.0;
+ this->alphaBitmap.rDest.right = this->alphaBitmap.rDest.left + bm.bmWidth;
+ this->alphaBitmap.rDest.bottom = this->alphaBitmap.rDest.top + bm.bmHeight;
+ this->alphaBitmap.rDest.left /= (rect.right - rect.left);
+ this->alphaBitmap.rDest.top /= (rect.bottom - rect.top);
+ this->alphaBitmap.rDest.right /= (rect.right - rect.left);
+ this->alphaBitmap.rDest.bottom /= (rect.bottom - rect.top);
+ // Alpha value for start
+ this->alphaBitmap.fAlpha = ALPHA_VALUE_START;
+
+ }
+}
+
+void DSDisplayOverlay::detach()
+{
+ // Clean up
+ DeleteObject(SelectObject(this->hdcBmp, this->hbmOld));
+ DeleteDC(this->hdcBmp);
+
+ this->hdcBmp = NULL;
+ this->hbmOld = NULL;
+ this->displayGraph = NULL;
+ this->window = NULL;
+}
+
+void DSDisplayOverlay::show(int value)
+{
+ // Store the ticks to count down
+ this->ticks = value;
+
+ // Compute alpha value decrement
+ this->alphaStep = (this->ticks > 0) ? ((ALPHA_VALUE_START - ALPHA_VALUE_STOP) / this->ticks) : 0;
+ this->alphaBitmap.fAlpha = ALPHA_VALUE_START;
+
+ this->internalUpdate();
+}
+
+void DSDisplayOverlay::update()
+{
+ if (this->displayGraph && (this->ticks > 0))
+ {
+ this->ticks--;
+
+ // Be sure alpha is in 0.0 .. 1.0 range.
+ float value = this->alphaBitmap.fAlpha;
+ value -= this->alphaStep;
+ this->alphaBitmap.fAlpha = (value >= 0.0f) ? value : 0.0f;
+
+ this->internalUpdate();
+ }
+}
+
+void DSDisplayOverlay::internalUpdate()
+{
+ HRESULT hr;
+
+ if (this->ticks > 0)
+ {
+ this->alphaBitmap.dwFlags = VMRBITMAP_HDC | VMRBITMAP_SRCCOLORKEY;
+ }
+ else
+ {
+ this->alphaBitmap.dwFlags = VMRBITMAP_DISABLE;
+ }
+
+ hr = this->displayGraph->getMixerBitmap()->SetAlphaBitmap(&this->alphaBitmap);
+ if (FAILED(hr))
+ {
+ cout << "Failed to mix overylay (" << hr << ")" << endl;
+ return;
+ }
+}
+
+#endif
diff --git a/plugins/pluginDirectShow/internals/DSDisplayOverlay.VMR9.cxx b/plugins/pluginDirectShow/internals/DSDisplayOverlay.VMR9.cxx
new file mode 100644
index 0000000..972945f
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSDisplayOverlay.VMR9.cxx
@@ -0,0 +1,207 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#if defined(VMR9) || defined(VMR9_WINDOWLESS)
+
+#define DIRECT3D_VERSION 0x0900
+
+#include <internals/DSDisplayOverlay.h>
+#include <internals/DSDisplayGraph.h>
+#include <internals/DSUtils.h>
+
+using namespace std;
+
+#define FILENAME _T("Overlay.png")
+#define ALPHA_VALUE_START 0.8f
+#define ALPHA_VALUE_STOP 0.0f
+
+
+DSDisplayOverlay::DSDisplayOverlay()
+{
+ this->window = NULL;
+ this->direct3DDevice = NULL;
+ this->direct3DSurface = NULL;
+
+ this->direct3D = Direct3DCreate9(D3D_SDK_VERSION);
+ if (!this->direct3D)
+ {
+ cout << "Cannot create Direct3D environment" << endl;
+ return;
+ }
+}
+
+DSDisplayOverlay::~DSDisplayOverlay()
+{
+ SAFE_RELEASE(this->direct3D);
+}
+
+void DSDisplayOverlay::attach(HWND parent, DSDisplayGraph *graph)
+{
+ HRESULT hr;
+
+ // Gets the handle of the parent and the graph
+ this->window = parent;
+ this->displayGraph = graph;
+
+ if (this->window)
+ {
+ D3DPRESENT_PARAMETERS d3dpp;
+ ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));
+ d3dpp.Windowed = TRUE;
+ d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
+
+ hr = this->direct3D->CreateDevice(
+ D3DADAPTER_DEFAULT,
+ D3DDEVTYPE_HAL,
+ this->window,
+ D3DCREATE_SOFTWARE_VERTEXPROCESSING,
+ &d3dpp,
+ &this->direct3DDevice);
+ if (FAILED(hr))
+ {
+ cout << "Cannot create Direct3D device" << endl;
+ return;
+ }
+
+ ZeroMemory(&this->overlayInfo, sizeof(D3DXIMAGE_INFO));
+ hr = D3DXGetImageInfoFromFile(FILENAME, &this->overlayInfo);
+ if (FAILED(hr))
+ {
+ cout << "Cannot stat overlay file" << endl;
+ return;
+ }
+
+ hr = this->direct3DDevice->CreateOffscreenPlainSurface(
+ this->overlayInfo.Width,
+ this->overlayInfo.Height,
+ D3DFMT_A8R8G8B8,
+ D3DPOOL_SYSTEMMEM,
+ &this->direct3DSurface,
+ NULL);
+ if (FAILED(hr))
+ {
+ cout << "Cannot create Direct3D surface" << endl;
+ return;
+ }
+
+ D3DCOLOR alphaKey = 0xFF000000;
+
+ hr = D3DXLoadSurfaceFromFile(this->direct3DSurface,
+ NULL,
+ NULL,
+ FILENAME,
+ NULL,
+ D3DX_FILTER_NONE,
+ alphaKey,
+ &this->overlayInfo);
+ if (FAILED(hr))
+ {
+ cout << "Cannot load overlay file" << endl;
+ return;
+ }
+
+ D3DVIEWPORT9 viewport;
+ ZeroMemory(&viewport, sizeof(D3DVIEWPORT9));
+
+ hr= this->direct3DDevice->GetViewport(&viewport);
+ if (FAILED(hr))
+ {
+ cout << "Cannot get view port" << endl;
+ return;
+ }
+
+ ZeroMemory(&this->alphaBitmap, sizeof(VMR9AlphaBitmap));
+ this->alphaBitmap.dwFlags = VMR9AlphaBitmap_EntireDDS;
+ this->alphaBitmap.hdc = NULL;
+ this->alphaBitmap.pDDS = this->direct3DSurface;
+ // Source rectangle
+ this->alphaBitmap.rSrc.left = 0;
+ this->alphaBitmap.rSrc.top = 0;
+ this->alphaBitmap.rSrc.right = this->overlayInfo.Width;
+ this->alphaBitmap.rSrc.bottom = this->overlayInfo.Height;
+ // Destination rectangle
+ this->alphaBitmap.rDest.left = (viewport.Width - this->overlayInfo.Width) / 2.0;
+ this->alphaBitmap.rDest.top = (viewport.Height - this->overlayInfo.Height) / 2.0;
+ this->alphaBitmap.rDest.right = this->alphaBitmap.rDest.left + this->overlayInfo.Width;
+ this->alphaBitmap.rDest.bottom = this->alphaBitmap.rDest.top + this->overlayInfo.Height;
+ this->alphaBitmap.rDest.left /= viewport.Width;
+ this->alphaBitmap.rDest.top /= viewport.Height;
+ this->alphaBitmap.rDest.right /= viewport.Width;
+ this->alphaBitmap.rDest.bottom /= viewport.Height;
+ // Alpha value for start
+ this->alphaBitmap.fAlpha = ALPHA_VALUE_START;
+ }
+}
+
+void DSDisplayOverlay::detach()
+{
+ SAFE_RELEASE(this->direct3DSurface);
+ SAFE_RELEASE(this->direct3DDevice);
+
+ this->displayGraph = NULL;
+ this->window = NULL;
+}
+
+void DSDisplayOverlay::show(int value)
+{
+ // Store the ticks to count down
+ this->ticks = value;
+
+ // Compute alpha value decrement
+ this->alphaStep = (this->ticks > 0) ? ((ALPHA_VALUE_START - ALPHA_VALUE_STOP) / this->ticks) : 0;
+ this->alphaBitmap.fAlpha = ALPHA_VALUE_START;
+
+ this->internalUpdate();
+}
+
+void DSDisplayOverlay::update()
+{
+ if (this->displayGraph && (this->ticks > 0))
+ {
+ this->ticks--;
+
+ // Be sure alpha is in 0.0 .. 1.0 range.
+ float value = this->alphaBitmap.fAlpha;
+ value -= this->alphaStep;
+ this->alphaBitmap.fAlpha = (value >= 0.0f) ? value : 0.0f;
+
+ this->internalUpdate();
+ }
+}
+
+void DSDisplayOverlay::internalUpdate()
+{
+ HRESULT hr;
+
+ if (this->ticks > 0)
+ {
+ this->alphaBitmap.dwFlags = VMR9AlphaBitmap_EntireDDS;
+ }
+ else
+ {
+ this->alphaBitmap.dwFlags = VMR9AlphaBitmap_Disable;
+ }
+
+ hr = this->displayGraph->getMixerBitmap()->SetAlphaBitmap(&this->alphaBitmap);
+ if (FAILED(hr))
+ {
+ cout << "Failed to mix overylay (" << hr << ")" << endl;
+ return;
+ }
+}
+
+#endif
diff --git a/plugins/pluginDirectShow/internals/DSDisplayOverlay.cxx b/plugins/pluginDirectShow/internals/DSDisplayOverlay.cxx
new file mode 100644
index 0000000..eb355c4
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSDisplayOverlay.cxx
@@ -0,0 +1,67 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#if !defined(VMR) && !defined(VMR9) && !defined(VMR9_WINDOWLESS)
+
+#include "internals/DSDisplayOverlay.h"
+#include "internals/DSDisplayGraph.h"
+
+#include <iostream>
+
+using namespace std;
+
+DSDisplayOverlay::DSDisplayOverlay()
+{
+}
+
+DSDisplayOverlay::~DSDisplayOverlay()
+{
+}
+
+void DSDisplayOverlay::attach(HWND parent, DSDisplayGraph *graph)
+{
+ this->displayGraph = graph;
+}
+
+void DSDisplayOverlay::detach()
+{
+ this->displayGraph = NULL;
+}
+
+void DSDisplayOverlay::show(int value)
+{
+ // Store the ticks to count down
+ this->ticks = value;
+
+ this->internalUpdate();
+}
+
+void DSDisplayOverlay::update()
+{
+ if (this->displayGraph && (this->ticks > 0))
+ {
+ this->ticks--;
+ this->internalUpdate();
+ }
+}
+
+void DSDisplayOverlay::internalUpdate()
+{
+ this->displayGraph->getSourceFilter()->showOverlay(this->ticks);
+}
+
+#endif
diff --git a/plugins/pluginDirectShow/internals/DSDisplayOverlay.h b/plugins/pluginDirectShow/internals/DSDisplayOverlay.h
new file mode 100644
index 0000000..0db887d
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSDisplayOverlay.h
@@ -0,0 +1,68 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#ifndef PLUGIN_DSHOW_DSDISPLAYOVERLAY_H
+#define PLUGIN_DSHOW_DSDISPLAYOVERLAY_H
+
+#include "plugin_dshow_config.h"
+#include <strmif.h>
+
+#if defined(VMR9) || defined(VMR9_WINDOWLESS)
+#include <D3D9.h>
+#include <D3Dx9.h>
+#include <vmr9.h>
+#endif
+
+class DSDisplayGraph;
+
+class DSDisplayOverlay
+{
+public:
+ DSDisplayOverlay();
+ virtual ~DSDisplayOverlay();
+
+ void attach(HWND parent, DSDisplayGraph *graph);
+ void detach();
+
+ void show(int value);
+ void update();
+
+private:
+ void internalUpdate();
+
+private:
+ HWND window;
+
+ DSDisplayGraph *displayGraph;
+ int ticks;
+
+#if defined(VMR)
+ HDC hdcBmp;
+ HBITMAP hbmOld;
+ VMRALPHABITMAP alphaBitmap;
+ float alphaStep;
+#elif defined(VMR9) || defined(VMR9_WINDOWLESS)
+ IDirect3D9 *direct3D;
+ IDirect3DDevice9 *direct3DDevice;
+ IDirect3DSurface9 *direct3DSurface;
+ D3DXIMAGE_INFO overlayInfo;
+ VMR9AlphaBitmap alphaBitmap;
+ float alphaStep;
+#endif
+};
+
+#endif
diff --git a/plugins/pluginDirectShow/internals/DSFrameRateFilter.cxx b/plugins/pluginDirectShow/internals/DSFrameRateFilter.cxx
new file mode 100644
index 0000000..cbf2a0a
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSFrameRateFilter.cxx
@@ -0,0 +1,120 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#include "internals/DSFrameRateFilter.h"
+
+#include <iostream>
+#include <string>
+
+using namespace std;
+
+#define FPS_INPUT 30
+#define FPS_OUTPUT 5
+
+// {7F9F08CF-139F-40b2-A283-01C4EC26A452}
+TDSHOW_DEFINE_GUID(CLSID_DSFrameRateFilter,
+0x7f9f08cf, 0x139f, 0x40b2, 0xa2, 0x83, 0x1, 0xc4, 0xec, 0x26, 0xa4, 0x52);
+
+DSFrameRateFilter::DSFrameRateFilter(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr)
+:CTransInPlaceFilter (tszName, punk, CLSID_DSFrameRateFilter, phr)
+{
+ this->m_rtFrameLength = (10000000)/FPS_OUTPUT;
+
+ this->m_inputFps = FPS_INPUT;
+ this->m_outputFps = FPS_OUTPUT;
+
+ this->m_iFrameNumber = 0;
+ this->m_progress = 0;
+ this->m_bProcessFrame = true;
+}
+
+DSFrameRateFilter::~DSFrameRateFilter()
+{
+}
+
+HRESULT DSFrameRateFilter::SetFps(int inputFps, int outputFps)
+{
+ if(inputFps <= 0 || outputFps <= 0)
+ {
+ return E_FAIL;
+ }
+
+ // Stop prcessing
+ this->m_bProcessFrame = false;
+
+ if (inputFps < outputFps) {
+ this->m_inputFps = this->m_outputFps = inputFps;
+ }
+ else {
+ this->m_outputFps = outputFps;
+ this->m_inputFps = inputFps;
+ }
+
+ // Restart processing
+ this->m_iFrameNumber = 0;
+ this->m_progress = 0;
+ this->m_bProcessFrame = true;
+
+ return S_OK;
+}
+
+HRESULT DSFrameRateFilter::Transform(IMediaSample *pSample)
+{
+ if(!this->m_bProcessFrame) return S_FALSE;
+
+ CheckPointer(pSample, E_POINTER);
+
+ HRESULT hr = S_OK;
+ HRESULT ret = S_FALSE;
+
+ pSample->SetTime(NULL, NULL);
+
+ // Drop frame?
+ if (this->m_iFrameNumber == 0) {
+ ret = S_OK;
+ }
+ else if (this->m_progress >= this->m_inputFps) {
+ this->m_progress -= this->m_inputFps;
+ ret = S_OK;
+ }
+
+ // Mark frame as accepted
+ if (ret == S_OK) {
+ // Set TRUE on every sample for uncompressed frames
+ pSample->SetSyncPoint(TRUE);
+ }
+
+ this->m_progress += this->m_outputFps;
+ this->m_iFrameNumber++;
+
+ return ret;
+}
+
+HRESULT DSFrameRateFilter::CheckInputType(const CMediaType* mtIn)
+{
+ return S_OK;
+}
+
+//Implement CreateInstance for your filter object. Typically, CreateInstance calls the constructor of your filter clas
+CUnknown * WINAPI DSFrameRateFilter::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
+{
+ DSFrameRateFilter *pNewObject = new DSFrameRateFilter(_T("Tdshow DirectShow Framerate Limiter Filter."), punk, phr );
+ if (pNewObject == NULL) {
+ *phr = E_OUTOFMEMORY;
+ }
+ return pNewObject;
+}
diff --git a/plugins/pluginDirectShow/internals/DSFrameRateFilter.h b/plugins/pluginDirectShow/internals/DSFrameRateFilter.h
new file mode 100644
index 0000000..9f2296e
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSFrameRateFilter.h
@@ -0,0 +1,64 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#ifndef PLUGIN_DSHOW_DSFRAMERATEFILTER_H
+#define PLUGIN_DSHOW_DSFRAMERATEFILTER_H
+
+#include "plugin_dshow_config.h"
+
+#include <streams.h>
+#include <math.h>
+
+class DSFrameRateFilter : public CTransInPlaceFilter
+{
+public:
+ DSFrameRateFilter(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr);
+ ~DSFrameRateFilter(void);
+
+public:
+ HRESULT Transform(IMediaSample *pSample);
+ HRESULT CheckInputType(const CMediaType* mtIn);
+
+public:
+ /**
+ * \def SetFps
+ * \brief fps1 define source .
+ */
+ HRESULT SetFps(int inputFps, int outputFps);
+
+ static CUnknown *WINAPI CreateInstance(LPUNKNOWN punk, HRESULT *phr);
+ DECLARE_IUNKNOWN;
+
+ /*STDMETHODIMP_(ULONG) NonDelegatingRelease()
+ {
+ if(InterlockedDecrement(&m_cRef) == 0)
+ {
+ delete this;
+ return 0;
+ }
+ return m_cRef;
+ }*/
+
+private:
+ int m_progress;
+ int m_inputFps, m_outputFps;
+ bool m_bProcessFrame;
+ REFERENCE_TIME m_rtFrameLength; // UNITS/fps
+ LONGLONG m_iFrameNumber;
+};
+
+#endif ////DSFrameRateFilter_H \ No newline at end of file
diff --git a/plugins/pluginDirectShow/internals/DSGrabber.cxx b/plugins/pluginDirectShow/internals/DSGrabber.cxx
new file mode 100644
index 0000000..e4dc3a7
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSGrabber.cxx
@@ -0,0 +1,292 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#include "internals/DSGrabber.h"
+#include "internals/DSDisplay.h"
+#include "internals/DSUtils.h"
+#include "internals/DSCaptureUtils.h"
+#include "internals/Resizer.h"
+#include "internals/DSUtils.h"
+#include "internals/DSCaptureGraph.h"
+#if !defined(_WIN32_WCE)
+# include "internals/DSScreenCastGraph.h"
+#endif
+
+#include "tsk_debug.h"
+
+#include <assert.h>
+
+using namespace std;
+
+DSGrabber::DSGrabber(HRESULT *hr, BOOL _screenCast)
+: mutex_buffer(NULL), preview(NULL)
+, screenCast(_screenCast)
+{
+#if defined(_WIN32_WCE)
+ assert(!screenCast);
+ this->graph = new DSCaptureGraph(this, hr);
+ CHECK_HR((*hr));
+#else
+ this->graph = screenCast ? dynamic_cast<DSBaseCaptureGraph*>(new DSScreenCastGraph(this, hr)) : dynamic_cast<DSBaseCaptureGraph*>(new DSCaptureGraph(this, hr));
+ CHECK_HR((*hr));
+ this->preview = new DSDisplay(hr);
+#endif
+
+ // Init the bitmap info header with default values
+ memset(&(this->bitmapInfo), 0, sizeof(BITMAPINFOHEADER));
+ this->bitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
+ this->bitmapInfo.biWidth = 352;
+ this->bitmapInfo.biHeight = 288;
+ this->bitmapInfo.biPlanes = 1;
+ this->bitmapInfo.biBitCount = 24;
+ this->bitmapInfo.biCompression = 0;
+ this->bitmapInfo.biXPelsPerMeter = 0;
+ this->bitmapInfo.biYPelsPerMeter = 0;
+ this->bitmapInfo.biClrUsed = 0;
+ this->bitmapInfo.biClrImportant = 0;
+
+ this->plugin_cb = NULL;
+ this->buffer = NULL;
+ this->mutex_buffer = tsk_mutex_create();
+
+bail: ;
+}
+
+DSGrabber::~DSGrabber()
+{
+ SAFE_DELETE_PTR ( this->graph );
+ SAFE_DELETE_PTR ( this->preview );
+ SAFE_DELETE_ARRAY ( this->buffer );
+ tsk_mutex_destroy(&this->mutex_buffer);
+}
+
+void DSGrabber::setCaptureDevice(const std::string &devicePath)
+{
+ this->graph->setSource(devicePath);
+}
+
+void DSGrabber::setCallback(tmedia_producer_enc_cb_f callback, const void* callback_data)
+{
+ this->plugin_cb = callback;
+ this->plugin_cb_data = callback_data;
+}
+
+void DSGrabber::start()
+{
+ if(this->graph->isPaused()){
+ this->graph->start();
+ this->preview->start();
+ return;
+ }
+
+ if (!this->graph->isRunning()){
+ first_buffer = true;
+
+ if(this->preview){
+ this->preview->start();
+ }
+ this->graph->connect();
+ this->graph->start();
+ }
+}
+
+void DSGrabber::pause()
+{
+ if(this->graph && this->graph->isRunning()){
+ this->graph->pause();
+ this->preview->pause();
+ }
+}
+
+void DSGrabber::stop()
+{
+ if (this->graph->isRunning()){
+ if(this->preview){
+ this->preview->stop();
+ }
+ this->graph->stop();
+ this->graph->disconnect();
+ }
+}
+
+bool DSGrabber::setCaptureParameters(int w, int h, int f)
+{
+ tsk_mutex_lock(this->mutex_buffer);
+
+ // Store the framerate
+ this->fps = f;
+ this->width = w;
+ this->height = h;
+
+ // Store the required dimensions
+ this->bitmapInfo.biWidth = this->width;
+ this->bitmapInfo.biHeight = this->height;
+ this->bitmapInfo.biBitCount = 24;
+ this->bitmapInfo.biSizeImage = (this->width * this->height * 3);
+
+ // Change the intermediate buffer
+ SAFE_DELETE_ARRAY ( this->buffer );
+ this->buffer = new BYTE[this->bitmapInfo.biSizeImage];
+ memset(this->buffer,0,this->bitmapInfo.biSizeImage);
+
+ // Find closest matching format to drive the source filter
+ DSCaptureFormat *fmt = NULL;
+ int score = 0;
+ std::vector<DSCaptureFormat> *formats = this->graph->getFormats();
+ std::vector<DSCaptureFormat>::iterator iter;
+ std::vector<DSCaptureFormat>::iterator last = formats->end();
+ for(iter = formats->begin(); iter != last; iter++){
+ int value = (*iter).getMatchScore(this->width, this->height);
+ if (value > score || !fmt){
+ score = value;
+ fmt = &(*iter);
+ }
+ }
+
+ // Setup source filter in the graph
+ HRESULT hr = this->graph->setParameters(fmt, this->fps);
+ // Set preview parameters
+ if(this->preview){
+ this->preview->setFps(this->fps);
+ this->preview->setSize(this->width, this->height);
+ }
+
+ tsk_mutex_unlock(this->mutex_buffer);
+
+ return SUCCEEDED(hr);
+}
+
+void DSGrabber::setPluginFirefox(bool value)
+{
+ if(this->preview){
+ this->preview->setPluginFirefox(value);
+ }
+}
+
+bool DSGrabber::setCaptureParameters(int format, int f)
+{
+ int w, h;
+ // Get size from the format
+ VIDEOFORMAT_TO_SIZE(format, w, h);
+ return this->setCaptureParameters(w, h, f);
+}
+
+int DSGrabber::getFramerate()
+{
+ return this->fps;
+}
+
+HRESULT DSGrabber::getConnectedMediaType(AM_MEDIA_TYPE *mediaType)
+{
+ if (!this->graph || !mediaType) {
+ return E_INVALIDARG;
+ }
+ return this->graph->getConnectedMediaType(mediaType);
+}
+
+HRESULT DSGrabber::SampleCB(double SampleTime, IMediaSample *pSample)
+{
+ return S_OK;
+}
+
+HRESULT DSGrabber::BufferCB(double SampleTime, BYTE *pBuffer, long BufferLen)
+{
+ HRESULT hr;
+
+ tsk_mutex_lock(this->mutex_buffer);
+
+ AM_MEDIA_TYPE mediaType;
+ hr = this->graph->getConnectedMediaType(&mediaType);
+ if (FAILED(hr) || !this->buffer){
+ return hr;
+ }
+
+ if(first_buffer){
+ first_buffer = false;
+
+ tsk_mutex_unlock(this->mutex_buffer);
+ return hr;
+ }
+
+ // Examine the format block.
+ if ((mediaType.formattype == FORMAT_VideoInfo) && (mediaType.cbFormat >= sizeof(VIDEOINFOHEADER)) && (mediaType.pbFormat != NULL) )
+ {
+ VIDEOINFOHEADER *pVih = reinterpret_cast<VIDEOINFOHEADER *>(mediaType.pbFormat);
+ BITMAPINFOHEADER* bih = &pVih->bmiHeader;
+
+ //int framerate = pVih->AvgTimePerFrame;
+ if( (bih->biHeight == this->bitmapInfo.biHeight) && (bih->biWidth == this->bitmapInfo.biWidth) && (bih->biBitCount == this->bitmapInfo.biBitCount) )
+ {
+ memmove(this->buffer, pBuffer, this->bitmapInfo.biSizeImage);
+ }
+ else
+ {
+ ResizeRGB(
+ bih,
+ (const unsigned char *) pBuffer,
+ &this->bitmapInfo,
+ (unsigned char *) this->buffer,
+ this->width,
+ this->height);
+ }
+
+ // for the network
+ if(this->plugin_cb){
+ this->plugin_cb(this->plugin_cb_data, this->buffer, (this->width*this->height*3));
+ }
+
+ // for the preview
+ if(this->preview){
+ this->preview->handleVideoFrame(this->buffer, this->width, this->height);
+ }
+ }
+
+ // Free the format
+#ifdef _WIN32_WCE
+ // Nothing had been allocated
+#else
+ FreeMediaType(mediaType);
+#endif
+
+ tsk_mutex_unlock(this->mutex_buffer);
+
+ return hr;
+}
+
+HRESULT DSGrabber::QueryInterface(REFIID iid, LPVOID *ppv)
+{
+#ifdef _WIN32_WCE
+ assert(1==0);
+#else
+ if( iid == IID_ISampleGrabberCB || iid == IID_IUnknown )
+ {
+ *ppv = (void *) static_cast<ISampleGrabberCB*>(this);
+ return NOERROR;
+ }
+#endif
+ return E_NOINTERFACE;
+}
+
+ULONG DSGrabber::AddRef()
+{
+ return 2;
+}
+
+ULONG DSGrabber::Release()
+{
+ return 1;
+} \ No newline at end of file
diff --git a/plugins/pluginDirectShow/internals/DSGrabber.h b/plugins/pluginDirectShow/internals/DSGrabber.h
new file mode 100644
index 0000000..64cde75
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSGrabber.h
@@ -0,0 +1,92 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#ifndef PLUGIN_DSHOW_DIRECTSHOW_GRABBER_H
+#define PLUGIN_DSHOW_DIRECTSHOW_GRABBER_H
+
+#include "plugin_dshow_config.h"
+
+#include "internals/DSBaseCaptureGraph.h"
+#include "internals/VideoFrame.h"
+
+#include "tinymedia/tmedia_producer.h"
+
+#include "tsk_mutex.h"
+
+class DSDisplay;
+
+#if defined(_WIN32_WCE)
+# include "internals/wince/DSISampleGrabberCB.h"
+#endif
+
+
+class DSGrabber : public
+#if defined(_WIN32_WCE)
+ DSISampleGrabberCB
+#else
+ ISampleGrabberCB
+#endif
+{
+public:
+ DSGrabber(HRESULT *hr, BOOL screenCast);
+ virtual ~DSGrabber();
+
+ void setCallback(tmedia_producer_enc_cb_f callback, const void* callback_data);
+ void setCaptureDevice(const std::string &devicePath);
+
+ virtual void start();
+ virtual void pause();
+ virtual void stop();
+
+ virtual bool setCaptureParameters(int format, int f);
+ virtual bool setCaptureParameters(int w, int h, int f);
+
+ virtual void setPluginFirefox(bool value);
+
+ virtual int getFramerate();
+ virtual HRESULT getConnectedMediaType(AM_MEDIA_TYPE *mediaType);
+
+ virtual HRESULT STDMETHODCALLTYPE SampleCB(double SampleTime, IMediaSample *pSample);
+ virtual HRESULT STDMETHODCALLTYPE BufferCB(double SampleTime, BYTE *pBuffer, long BufferLen);
+
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject);
+ virtual ULONG STDMETHODCALLTYPE AddRef();
+ virtual ULONG STDMETHODCALLTYPE Release();
+
+ DSDisplay *preview;
+
+private:
+ int width;
+ int height;
+ int fps;
+
+ DSBaseCaptureGraph *graph;
+
+ //VideoFrame *currentFrame;
+ BITMAPINFOHEADER bitmapInfo;
+ BYTE *buffer;
+
+ tsk_mutex_handle_t *mutex_buffer;
+
+ BOOL first_buffer;
+ BOOL screenCast;
+
+ const void* plugin_cb_data;
+ tmedia_producer_enc_cb_f plugin_cb;
+};
+
+#endif
diff --git a/plugins/pluginDirectShow/internals/DSOutputFilter.cxx b/plugins/pluginDirectShow/internals/DSOutputFilter.cxx
new file mode 100644
index 0000000..ab5aa0f
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSOutputFilter.cxx
@@ -0,0 +1,113 @@
+/*
+* Copyright (C) 2010-2011 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#include "internals/DSOutputFilter.h"
+#include "internals/DSOutputStream.h"
+#include "internals/DSUtils.h"
+
+#include "tsk_memory.h"
+
+DSOutputFilter::DSOutputFilter(LPUNKNOWN pUnk, HRESULT *phr)
+: CSource(_T("TDSHOW_OUTPUT"), pUnk, CLSID_TdshowOutputFilter)
+{
+#if !(defined(_WIN32_WCE) && defined(_DEBUG))
+ CAutoLock cAutoLock(&m_cStateLock);
+#endif
+
+ // Add one source stream (output pin)!
+ this->outputStream = new DSOutputStream(phr, this, _T("Out"));
+}
+
+DSOutputFilter::~DSOutputFilter()
+{
+ //SAFE_RELEASE(this->outputStream);
+}
+
+void DSOutputFilter::setBuffer(void *pointer, int size)
+{
+ this->outputStream->lockBuffer();
+ if(pointer && size){
+ if(this->outputStream->buffer_size != size){
+ if((this->outputStream->buffer = tsk_realloc(this->outputStream->buffer, size))){
+ this->outputStream->buffer_size = size;
+ }
+ else goto done;
+ }
+ memcpy(this->outputStream->buffer, pointer, size);
+ }
+done:
+ this->outputStream->unlockBuffer();
+}
+
+void DSOutputFilter::getMediaType(AM_MEDIA_TYPE* &pmt)
+{
+ //if(pmt)
+ //{
+ // memcpy(pmt, &this->outputStream->pmt, sizeof(AM_MEDIA_TYPE));
+ //}
+}
+
+HRESULT DSOutputFilter::setMediaType(const AM_MEDIA_TYPE* pmt)
+{
+ return this->ReconnectPin(this->outputStream, pmt);
+}
+
+HRESULT DSOutputFilter::setImageFormat(UINT width, UINT height)
+{
+ return this->outputStream->setImageFormat(width, height);
+}
+
+bool DSOutputFilter::getImageFormat(UINT &width, UINT &height)
+{
+ if(this->outputStream){
+ return this->outputStream->getImageFormat(width, height);
+ }
+ return false;
+}
+
+void DSOutputFilter::setFps(int fps_)
+{
+ this->outputStream->setFps(fps_);
+}
+
+void DSOutputFilter::showOverlay(int value)
+{
+ this->outputStream->showOverlay(value);
+}
+
+void DSOutputFilter::reset()
+{
+ this->outputStream->frameNumber = 0;
+ this->outputStream->lockBuffer();
+ this->outputStream->buffer = NULL;
+ this->outputStream->buffer_size = 0;
+ this->outputStream->unlockBuffer();
+}
+
+#ifdef _WIN32_WCE
+STDMETHODIMP_(ULONG) DSOutputFilter::NonDelegatingRelease()
+{
+ if(InterlockedDecrement(&m_cRef) == 0)
+ {
+ delete this;
+ return 0;
+ }
+ return m_cRef;
+}
+#endif
diff --git a/plugins/pluginDirectShow/internals/DSOutputFilter.h b/plugins/pluginDirectShow/internals/DSOutputFilter.h
new file mode 100644
index 0000000..fea2d23
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSOutputFilter.h
@@ -0,0 +1,112 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#ifndef PLUGIN_DSHOW_DSOUTPUTFILTER_H
+#define PLUGIN_DSHOW_DSOUTPUTFILTER_H
+
+#include "plugin_dshow_config.h"
+
+#include "internals/DSBufferWriter.h"
+#include <streams.h>
+
+class DSOutputStream;
+
+// {17D9D5CB-850D-4339-B72A-F72D084D8D64}
+TDSHOW_DEFINE_GUID(CLSID_TdshowOutputFilter,
+0x17d9d5cb, 0x850d, 0x4339, 0xb7, 0x2a, 0xf7, 0x2d, 0x8, 0x4d, 0x8d, 0x64);
+
+class DSOutputFilter : public CSource, public DSBufferWriter
+{
+public:
+ DSOutputFilter(LPUNKNOWN pUnk, HRESULT *phr);
+ virtual ~DSOutputFilter();
+
+ //static CUnknown * WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
+ DECLARE_IUNKNOWN;
+
+ virtual void setBuffer(void *pointer, int size);
+ virtual inline HRESULT setImageFormat(UINT width, UINT height);
+ virtual bool getImageFormat(UINT &width, UINT &height);
+
+ virtual void setFps(int fps_);
+ virtual void showOverlay(int value);
+
+ virtual void getMediaType(AM_MEDIA_TYPE* &pmt);
+ virtual HRESULT setMediaType(const AM_MEDIA_TYPE* pmt);
+
+ void reset();
+
+#ifdef _WIN32_WCE
+ STDMETHODIMP_(ULONG) NonDelegatingRelease();
+#endif
+
+//protected:
+#ifdef _WIN32_WCE
+ /*STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
+ {
+ CheckPointer(ppv, E_POINTER);
+
+ if (riid == IID_IBaseFilter
+ || riid == IID_IBaseFilter
+ || riid == IID_IUnknown
+ || riid == IID_IMediaFilter
+ )
+ {
+ return GetInterface((IBaseFilter *) this, ppv);
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+ };
+
+ STDMETHODIMP_(ULONG) AddRef() {
+ //return GetOwner()->AddRef();
+ //return 1;
+ return (ULONG)InterlockedIncrement(&m_cRef);
+ };
+
+ STDMETHODIMP_(ULONG) Release() {
+ LONG lRefCount = InterlockedDecrement(&m_cRef);
+ if(m_cRef < 1) delete this;
+ return (ULONG)m_cRef;
+ };
+
+ STDMETHODIMP_(ULONG) NonDelegatingAddRef()
+ {
+ return InterlockedIncrement(&m_cRef);
+ }*/
+#endif
+/*
+ STDMETHODIMP_(ULONG) NonDelegatingRelease()
+ {
+ if(InterlockedDecrement(&m_cRef) == 0)
+ {
+ delete this;
+ return 0;
+ }
+ return m_cRef;
+ }*/
+
+private:
+ DSOutputStream *outputStream;
+
+ friend class DSOutputStream;
+};
+
+#endif
diff --git a/plugins/pluginDirectShow/internals/DSOutputStream.cxx b/plugins/pluginDirectShow/internals/DSOutputStream.cxx
new file mode 100644
index 0000000..670d0ae
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSOutputStream.cxx
@@ -0,0 +1,313 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#include "internals/DSOutputStream.h"
+#include "internals/DSOutputFilter.h"
+#include "internals/DSUtils.h"
+
+#include <iostream>
+
+#include "tsk_memory.h"
+
+using namespace std;
+
+#define DEFAULT_FPS 15
+
+#define MEMCPY_WORKAROUND 1
+
+// Overlay
+#define OVERLAY 0
+#define OVERLAY_TEXT TEXT("Press ESC to exit full screen mode")
+#define OVERLAY_DURATION 3 // in seconds
+
+DSOutputStream::DSOutputStream(HRESULT *phr, DSOutputFilter *pParent, LPCWSTR pPinName)
+: CSourceStream(_T("DSOutputStream"), phr, pParent, pPinName)
+{
+#if !(defined(_WIN32_WCE) && defined(_DEBUG))
+ CAutoLock cAutoLock(m_pFilter->pStateLock());
+#endif
+
+ this->buffer = NULL;
+ this->buffer_size = NULL;
+
+ this->frameNumber = 0;
+ this->frameLength = (1000)/DEFAULT_FPS;
+ this->fps = DEFAULT_FPS;
+
+ this->width = 352;
+ this->height = 288;
+
+ this->overlay = false;
+
+ this->paintBuffer = NULL;
+ this->paintDC = NULL;
+ this->hDibSection = NULL;
+ this->hObject = NULL;
+
+ this->mutex = tsk_mutex_create();
+}
+
+DSOutputStream::~DSOutputStream()
+{
+ TSK_FREE(this->buffer);
+ tsk_mutex_destroy(&this->mutex);
+ // TODO : Is there anything to free ???
+}
+
+void DSOutputStream::setFps(int fps_)
+{
+ this->fps = fps_;
+ this->frameLength = (1000)/this->fps;
+}
+
+void DSOutputStream::showOverlay(int value)
+{
+ if (value == 0){
+ this->overlay = false;
+ }
+ this->overlay = (value > 0);
+}
+
+HRESULT DSOutputStream::setImageFormat(UINT width, UINT height)
+{
+ if ((this->width == width) && (this->height == height)) return S_FALSE;
+
+ this->width = width;
+ this->height = height;
+
+ this->frameNumber = 0;
+
+ return S_OK;
+}
+
+bool DSOutputStream::getImageFormat(UINT &width, UINT &height)
+{
+ width = this->width;
+ height = this->height;
+ return true;
+}
+
+HRESULT DSOutputStream::GetMediaType(CMediaType *pMediaType)
+{
+ HRESULT hr = S_OK;
+#if !(defined(_WIN32_WCE) && defined(_DEBUG))
+ CAutoLock lock(m_pFilter->pStateLock());
+#endif
+
+ ZeroMemory(pMediaType, sizeof(CMediaType));
+
+ VIDEOINFO *pvi = (VIDEOINFO *)pMediaType->AllocFormatBuffer(sizeof(VIDEOINFO));
+ if (NULL == pvi)
+ return E_OUTOFMEMORY;
+
+ ZeroMemory(pvi, sizeof(VIDEOINFO));
+
+ pvi->bmiHeader.biCompression = BI_RGB;
+ pvi->bmiHeader.biBitCount = 24;
+ pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pvi->bmiHeader.biWidth = this->width;
+ pvi->bmiHeader.biHeight = this->height;
+ pvi->bmiHeader.biPlanes = 1;
+ pvi->bmiHeader.biSizeImage = GetBitmapSize(&pvi->bmiHeader);
+ pvi->bmiHeader.biClrImportant = 0;
+
+ // Frame rate
+ pvi->AvgTimePerFrame = DS_MILLIS_TO_100NS(1000/this->fps);
+
+ SetRectEmpty(&(pvi->rcSource)); // we want the whole image area rendered.
+ SetRectEmpty(&(pvi->rcTarget)); // no particular destination rectangle
+
+ pMediaType->SetType(&MEDIATYPE_Video);
+ pMediaType->SetFormatType(&FORMAT_VideoInfo);
+ pMediaType->SetTemporalCompression(FALSE);
+
+ pMediaType->SetSubtype(&MEDIASUBTYPE_RGB24);
+ pMediaType->SetSampleSize(pvi->bmiHeader.biSizeImage);
+
+ bitmapInfo.bmiHeader = pvi->bmiHeader;
+
+ return hr;
+}
+
+HRESULT DSOutputStream::DecideBufferSize(IMemAllocator *pMemAlloc, ALLOCATOR_PROPERTIES *pProperties)
+{
+ CheckPointer(pMemAlloc, E_POINTER);
+ CheckPointer(pProperties, E_POINTER);
+
+#if !(defined(_WIN32_WCE) && defined(_DEBUG))
+ CAutoLock cAutoLock(m_pFilter->pStateLock());
+#endif
+
+ HRESULT hr = NOERROR;
+
+ VIDEOINFO *pvi = (VIDEOINFO *) m_mt.Format();
+ pProperties->cBuffers = 1;
+ pProperties->cbBuffer = pvi->bmiHeader.biSizeImage;
+
+ // Ask the allocator to reserve us some sample memory. NOTE: the function
+ // can succeed (return NOERROR) but still not have allocated the
+ // memory that we requested, so we must check we got whatever we wanted.
+ ALLOCATOR_PROPERTIES Actual;
+ hr = pMemAlloc->SetProperties(pProperties,&Actual);
+ if(FAILED(hr)){
+ return hr;
+ }
+
+ // Is this allocator unsuitable?
+ if(Actual.cbBuffer < pProperties->cbBuffer)
+ {
+ return E_FAIL;
+ }
+
+ // Make sure that we have only 1 buffer (we erase the ball in the
+ // old buffer to save having to zero a 200k+ buffer every time
+ // we draw a frame)
+ return NOERROR;
+}
+
+HRESULT DSOutputStream::OnThreadCreate()
+{
+#if OVERLAY
+ hDibSection = CreateDIBSection(NULL, (BITMAPINFO *) &bitmapInfo, DIB_RGB_COLORS, &paintBuffer, NULL, 0);
+
+ HDC hDC = GetDC(NULL);
+ paintDC = CreateCompatibleDC(hDC);
+ SetMapMode(paintDC, GetMapMode(hDC));
+ SetBkMode(paintDC, TRANSPARENT);
+ SetTextColor(paintDC, RGB(255,255,255));
+
+ hObject = SelectObject(paintDC, hDibSection);
+#endif
+
+ return CSourceStream::OnThreadCreate();
+}
+
+HRESULT DSOutputStream::OnThreadDestroy()
+{
+#if OVERLAY
+ if (paintDC) DeleteDC(paintDC);
+ if (hObject) DeleteObject(hObject);
+
+ if (paintBuffer)
+ {
+ //delete[] paintBuffer; // will be done
+ //paintBuffer = NULL;
+ }
+#endif
+ return CSourceStream::OnThreadDestroy();
+}
+
+inline HRESULT DSOutputStream::DrawOverLay(void *pBuffer, long lSize)
+{
+ // called only #if OVERLAY
+ CopyMemory(paintBuffer, pBuffer, lSize);
+
+ // Draw the current frame
+#ifdef _WIN32_WCE
+
+#else
+ if( !TextOut( paintDC, 0, 0, OVERLAY_TEXT, (int)_tcslen( OVERLAY_TEXT ) ) ) return E_FAIL;
+#endif
+
+ CopyMemory(pBuffer, paintBuffer, lSize);
+
+ return S_OK;
+}
+
+static __inline void TransfertBuffer(void* src, void* dest, long lSize)
+{
+ __try
+ {
+#if MEMCPY_WORKAROUND
+ //#ifdef _WIN32_WCE
+ memmove(dest, src, lSize);
+ /*#else
+ unsigned char * pDst = (unsigned char *) dest;
+
+ if(src){
+ unsigned char const * pSrc = (unsigned char const *) src;
+ for( register int i=0; ((i< lSize) && src); i++) *pDst++ = *pSrc++;
+ }else{
+ for( register int i=0; i< lSize; i++) *pDst++ = 0;
+ }
+ #endif*/
+#else
+ CopyMemory(dest, src, lSize); //BUGGY
+#endif
+ }
+ __except(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
+ {
+ //ZeroMemory(dest, sizeof(void*));
+ }
+}
+
+HRESULT DSOutputStream::FillBuffer(IMediaSample *pSample)
+{
+ CheckPointer(pSample, E_POINTER);
+#if !(defined(_WIN32_WCE) && defined(_DEBUG))
+ CAutoLock lock(m_pFilter->pStateLock());
+#endif
+
+ HRESULT hr;
+ BYTE *pBuffer = NULL;
+ long lSize, lDataSize;
+
+ hr = pSample->GetPointer(&pBuffer);
+ if (SUCCEEDED(hr))
+ {
+ lDataSize = lSize = pSample->GetSize();
+
+ // Check that we're still using video
+ //ASSERT(m_mt.formattype == FORMAT_VideoInfo);
+
+ if (this->buffer)
+ {
+#if OVERLAY
+ if (this->overlay)
+ {
+ DrawOverLay(this->buffer, lSize);
+ }
+#endif
+ // Why try do not work, see: http://msdn2.microsoft.com/en-us/library/xwtb73ad(vs.80).aspx
+ this->lockBuffer();
+ lDataSize = TSK_MIN(lSize, this->buffer_size);
+ TransfertBuffer(this->buffer, (void*)pBuffer, lDataSize);
+ this->unlockBuffer();
+ }
+ else
+ {
+ // Avoid caching last image
+ memset((void*)pBuffer, NULL, lSize);
+ }
+
+ REFERENCE_TIME rtStart = DS_MILLIS_TO_100NS(this->frameNumber * this->frameLength);
+ REFERENCE_TIME rtStop = rtStart + DS_MILLIS_TO_100NS(this->frameLength);
+
+ this->frameNumber++;
+
+ pSample->SetTime(&rtStart, &rtStop);
+ //pSample->SetMediaTime(&rtStart, &rtStop);
+ pSample->SetActualDataLength(lDataSize);
+ pSample->SetPreroll(FALSE);
+ pSample->SetDiscontinuity(FALSE);
+ }
+
+ // Set TRUE on every sample for uncompressed frames (KEYFRAME)
+ pSample->SetSyncPoint(TRUE);
+
+ return S_OK;
+}
diff --git a/plugins/pluginDirectShow/internals/DSOutputStream.h b/plugins/pluginDirectShow/internals/DSOutputStream.h
new file mode 100644
index 0000000..db3ede4
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSOutputStream.h
@@ -0,0 +1,90 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#ifndef PLUGIN_DSHOW_DSOUTPUTSTREAM_H
+#define PLUGIN_DSHOW_DSOUTPUTSTREAM_H
+
+#include "plugin_dshow_config.h"
+
+#include <streams.h>
+
+#include "tsk_mutex.h"
+
+class DSOutputFilter;
+
+class DSOutputStream : public CSourceStream
+{
+public:
+ DSOutputStream(HRESULT *phr, DSOutputFilter *pParent, LPCWSTR pPinName);
+ virtual ~DSOutputStream();
+
+ void setFps(int fps_);
+ void showOverlay(int value);
+
+ HRESULT setImageFormat(UINT width, UINT height);
+ bool getImageFormat(UINT &width, UINT &height);
+ STDMETHODIMP Notify(IBaseFilter *pSelf, Quality q) { return E_NOTIMPL; };
+ inline bool lockBuffer() {
+ if (this->mutex) {
+ return tsk_mutex_lock(this->mutex) == 0;
+ }
+ return false;
+ }
+ inline bool unlockBuffer() {
+ if (this->mutex) {
+ return tsk_mutex_unlock(this->mutex) == 0;
+ }
+ return false;
+ }
+
+public:
+ void *buffer;
+ int buffer_size;
+ LONGLONG frameNumber;
+
+protected: // Overrides
+ HRESULT GetMediaType(CMediaType *pMediaType);
+ HRESULT DecideBufferSize(IMemAllocator *pMemAlloc, ALLOCATOR_PROPERTIES *pProperties);
+ HRESULT OnThreadCreate();
+ HRESULT OnThreadDestroy();
+ HRESULT FillBuffer(IMediaSample *pSample);
+
+private:
+ inline HRESULT DrawOverLay(void *pBuffer, long lSize);
+
+private:
+ // TIMING
+ REFERENCE_TIME frameLength;
+ int fps;
+
+ // sizing
+ UINT width;
+ UINT height;
+
+ // overlaying
+ bool overlay;
+ BITMAPINFO bitmapInfo;
+ void *paintBuffer;
+ HDC paintDC;
+ HBITMAP hDibSection;
+ HGDIOBJ hObject;
+
+ tsk_mutex_handle_t* mutex;
+};
+
+
+#endif
diff --git a/plugins/pluginDirectShow/internals/DSPushSource.h b/plugins/pluginDirectShow/internals/DSPushSource.h
new file mode 100644
index 0000000..140d9bd
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSPushSource.h
@@ -0,0 +1,496 @@
+//------------------------------------------------------------------------------
+// File: PushSource.H
+//
+// Desc: DirectShow sample code - In-memory push mode source filter
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------------------------
+#ifndef PLUGIN_DSHOW_DSPUSHSOURCE_H
+#define PLUGIN_DSHOW_DSPUSHSOURCE_H
+
+#include "plugin_dshow_config.h"
+
+#include <strsafe.h>
+
+// UNITS = 10 ^ 7
+// UNITS / 30 = 30 fps;
+// UNITS / 20 = 20 fps, etc
+const REFERENCE_TIME FPS_30 = UNITS / 30;
+const REFERENCE_TIME FPS_20 = UNITS / 20;
+const REFERENCE_TIME FPS_10 = UNITS / 10;
+const REFERENCE_TIME FPS_5 = UNITS / 5;
+const REFERENCE_TIME FPS_4 = UNITS / 4;
+const REFERENCE_TIME FPS_3 = UNITS / 3;
+const REFERENCE_TIME FPS_2 = UNITS / 2;
+const REFERENCE_TIME FPS_1 = UNITS / 1;
+
+const REFERENCE_TIME rtDefaultFrameLength = FPS_10;
+
+// Filter name strings
+#define g_wszPushBitmap L"PushSource Bitmap Filter"
+#define g_wszPushBitmapSet L"PushSource BitmapSet Filter"
+#define g_wszPushDesktop L"PushSource Desktop Filter"
+
+// Number of bitmap files to load in the CPushPinBitmapSet class
+#define NUM_FILES 5
+
+// {3FD3081A-A8C9-4958-9F75-07EC89690024}
+TDSHOW_DEFINE_GUID(CLSID_PushSourceDesktop,
+0x3fd3081a, 0xa8c9, 0x4958, 0x9f, 0x75, 0x7, 0xec, 0x89, 0x69, 0x0, 0x24);
+
+
+
+/**********************************************
+ *
+ * Class declarations
+ *
+ **********************************************/
+
+class CPushPinBitmap : public CSourceStream
+{
+protected:
+
+ int m_FramesWritten; // To track where we are in the file
+ BOOL m_bZeroMemory; // Do we need to clear the buffer?
+ CRefTime m_rtSampleTime; // The time stamp for each sample
+
+ BITMAPINFO *m_pBmi; // Pointer to the bitmap header
+ DWORD m_cbBitmapInfo; // Size of the bitmap header
+
+ // File opening variables
+ HANDLE m_hFile; // Handle returned from CreateFile
+ BYTE * m_pFile; // Points to beginning of file buffer
+ BYTE * m_pImage; // Points to pixel bits
+
+ int m_iFrameNumber;
+ const REFERENCE_TIME m_rtFrameLength;
+
+ CCritSec m_cSharedState; // Protects our internal state
+ CImageDisplay m_Display; // Figures out our media type for us
+
+public:
+
+ CPushPinBitmap(HRESULT *phr, CSource *pFilter);
+ ~CPushPinBitmap();
+
+ // Override the version that offers exactly one media type
+ HRESULT GetMediaType(CMediaType *pMediaType);
+ HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest);
+ HRESULT FillBuffer(IMediaSample *pSample);
+
+ // Quality control
+ // Not implemented because we aren't going in real time.
+ // If the file-writing filter slows the graph down, we just do nothing, which means
+ // wait until we're unblocked. No frames are ever dropped.
+ STDMETHODIMP Notify(IBaseFilter *pSelf, Quality q)
+ {
+ return E_FAIL;
+ }
+
+};
+
+
+class CPushPinBitmapSet : public CSourceStream
+{
+protected:
+
+ int m_FramesWritten; // To track where we are in the file
+ BOOL m_bZeroMemory; // Do we need to clear the buffer?
+ CRefTime m_rtSampleTime; // The time stamp for each sample
+
+ BITMAPINFO *m_pBmi[NUM_FILES]; // Pointer to the bitmap headers
+ DWORD m_cbBitmapInfo[NUM_FILES]; // Size of the bitmap headers
+
+ // File opening variables
+ HANDLE m_hFile[NUM_FILES]; // Handles returned from CreateFile
+ BYTE * m_pFile[NUM_FILES]; // Points to beginning of file buffers
+ BYTE * m_pImage[NUM_FILES]; // Points to pixel bits
+ BOOL m_bFilesLoaded;
+
+ int m_iCurrentBitmap; // Which bitmap is being displayed
+ int m_iFrameNumber; // How many frames have been displayed
+ const REFERENCE_TIME m_rtFrameLength; // Duration of one frame
+
+ CCritSec m_cSharedState; // Protects our internal state
+ CImageDisplay m_Display; // Figures out our media type for us
+
+public:
+
+ CPushPinBitmapSet(HRESULT *phr, CSource *pFilter);
+ ~CPushPinBitmapSet();
+
+ // Override the version that offers exactly one media type
+ HRESULT GetMediaType(CMediaType *pMediaType);
+ HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest);
+ HRESULT FillBuffer(IMediaSample *pSample);
+
+ // Quality control
+ // Not implemented because we aren't going in real time.
+ // If the file-writing filter slows the graph down, we just do nothing, which means
+ // wait until we're unblocked. No frames are ever dropped.
+ STDMETHODIMP Notify(IBaseFilter *pSelf, Quality q)
+ {
+ return E_FAIL;
+ }
+
+};
+
+
+class CPushPinDesktop : public CSourceStream
+{
+protected:
+
+ int m_FramesWritten; // To track where we are in the file
+ BOOL m_bZeroMemory; // Do we need to clear the buffer?
+ CRefTime m_rtSampleTime; // The time stamp for each sample
+
+ int m_iFrameNumber;
+ const REFERENCE_TIME m_rtFrameLength;
+
+ RECT m_rScreen; // Rect containing entire screen coordinates
+
+ int m_iImageHeight; // The current image height
+ int m_iImageWidth; // And current image width
+ int m_iRepeatTime; // Time in msec between frames
+ int m_nCurrentBitDepth; // Screen bit depth
+
+ CMediaType m_MediaType;
+ CCritSec m_cSharedState; // Protects our internal state
+ CImageDisplay m_Display; // Figures out our media type for us
+
+ HWND m_hSrcHwnd; // Handle to the window to grab
+
+public:
+
+ CPushPinDesktop(HRESULT *phr, CSource *pFilter);
+ ~CPushPinDesktop();
+
+ // Override the version that offers exactly one media type
+ HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest);
+ HRESULT FillBuffer(IMediaSample *pSample);
+
+ // Set the agreed media type and set up the necessary parameters
+ HRESULT SetMediaType(const CMediaType *pMediaType);
+
+ // Support multiple display formats
+ HRESULT CheckMediaType(const CMediaType *pMediaType);
+ HRESULT GetMediaType(int iPosition, CMediaType *pmt);
+
+ // Quality control
+ // Not implemented because we aren't going in real time.
+ // If the file-writing filter slows the graph down, we just do nothing, which means
+ // wait until we're unblocked. No frames are ever dropped.
+ STDMETHODIMP Notify(IBaseFilter *pSelf, Quality q)
+ {
+ return E_FAIL;
+ }
+
+ HRESULT SetSrcHwnd(HWND hWnd)
+ {
+ m_hSrcHwnd = hWnd;
+ return S_OK;
+ }
+
+};
+
+
+
+class CPushSourceBitmap : public CSource
+{
+
+private:
+ // Constructor is private because you have to use CreateInstance
+ CPushSourceBitmap(IUnknown *pUnk, HRESULT *phr);
+ ~CPushSourceBitmap();
+
+ CPushPinBitmap *m_pPin;
+
+public:
+ static CUnknown * WINAPI CreateInstance(IUnknown *pUnk, HRESULT *phr);
+
+};
+
+
+class CPushSourceBitmapSet : public CSource
+{
+
+private:
+ // Constructor is private because you have to use CreateInstance
+ CPushSourceBitmapSet(IUnknown *pUnk, HRESULT *phr);
+ ~CPushSourceBitmapSet();
+
+ CPushPinBitmapSet *m_pPin;
+
+public:
+ static CUnknown * WINAPI CreateInstance(IUnknown *pUnk, HRESULT *phr);
+
+};
+
+
+class CPushSourceDesktop : public CSource
+{
+
+private:
+ // Constructor is private because you have to use CreateInstance
+ CPushSourceDesktop(IUnknown *pUnk, HRESULT *phr);
+ ~CPushSourceDesktop();
+
+ CPushPinDesktop *m_pPin;
+
+public:
+ static CUnknown * WINAPI CreateInstance(IUnknown *pUnk, HRESULT *phr);
+ DECLARE_IUNKNOWN;
+
+ HRESULT SetSrcHwnd(HWND hWnd);
+};
+
+
+#endif /* PLUGIN_DSHOW_DSPUSHSOURCE_H */
+//------------------------------------------------------------------------------
+// File: PushSource.H
+//
+// Desc: DirectShow sample code - In-memory push mode source filter
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------------------------
+#ifndef PLUGIN_DSHOW_DSPUSHSOURCE_H
+#define PLUGIN_DSHOW_DSPUSHSOURCE_H
+
+#include "plugin_dshow_config.h"
+
+#include <strsafe.h>
+
+// UNITS = 10 ^ 7
+// UNITS / 30 = 30 fps;
+// UNITS / 20 = 20 fps, etc
+const REFERENCE_TIME FPS_30 = UNITS / 30;
+const REFERENCE_TIME FPS_20 = UNITS / 20;
+const REFERENCE_TIME FPS_10 = UNITS / 10;
+const REFERENCE_TIME FPS_5 = UNITS / 5;
+const REFERENCE_TIME FPS_4 = UNITS / 4;
+const REFERENCE_TIME FPS_3 = UNITS / 3;
+const REFERENCE_TIME FPS_2 = UNITS / 2;
+const REFERENCE_TIME FPS_1 = UNITS / 1;
+
+const REFERENCE_TIME rtDefaultFrameLength = FPS_10;
+
+// Filter name strings
+#define g_wszPushBitmap L"PushSource Bitmap Filter"
+#define g_wszPushBitmapSet L"PushSource BitmapSet Filter"
+#define g_wszPushDesktop L"PushSource Desktop Filter"
+
+// Number of bitmap files to load in the CPushPinBitmapSet class
+#define NUM_FILES 5
+
+// {3FD3081A-A8C9-4958-9F75-07EC89690024}
+TDSHOW_DEFINE_GUID(CLSID_PushSourceDesktop,
+0x3fd3081a, 0xa8c9, 0x4958, 0x9f, 0x75, 0x7, 0xec, 0x89, 0x69, 0x0, 0x24);
+
+
+
+/**********************************************
+ *
+ * Class declarations
+ *
+ **********************************************/
+
+class CPushPinBitmap : public CSourceStream
+{
+protected:
+
+ int m_FramesWritten; // To track where we are in the file
+ BOOL m_bZeroMemory; // Do we need to clear the buffer?
+ CRefTime m_rtSampleTime; // The time stamp for each sample
+
+ BITMAPINFO *m_pBmi; // Pointer to the bitmap header
+ DWORD m_cbBitmapInfo; // Size of the bitmap header
+
+ // File opening variables
+ HANDLE m_hFile; // Handle returned from CreateFile
+ BYTE * m_pFile; // Points to beginning of file buffer
+ BYTE * m_pImage; // Points to pixel bits
+
+ int m_iFrameNumber;
+ const REFERENCE_TIME m_rtFrameLength;
+
+ CCritSec m_cSharedState; // Protects our internal state
+ CImageDisplay m_Display; // Figures out our media type for us
+
+public:
+
+ CPushPinBitmap(HRESULT *phr, CSource *pFilter);
+ ~CPushPinBitmap();
+
+ // Override the version that offers exactly one media type
+ HRESULT GetMediaType(CMediaType *pMediaType);
+ HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest);
+ HRESULT FillBuffer(IMediaSample *pSample);
+
+ // Quality control
+ // Not implemented because we aren't going in real time.
+ // If the file-writing filter slows the graph down, we just do nothing, which means
+ // wait until we're unblocked. No frames are ever dropped.
+ STDMETHODIMP Notify(IBaseFilter *pSelf, Quality q)
+ {
+ return E_FAIL;
+ }
+
+};
+
+
+class CPushPinBitmapSet : public CSourceStream
+{
+protected:
+
+ int m_FramesWritten; // To track where we are in the file
+ BOOL m_bZeroMemory; // Do we need to clear the buffer?
+ CRefTime m_rtSampleTime; // The time stamp for each sample
+
+ BITMAPINFO *m_pBmi[NUM_FILES]; // Pointer to the bitmap headers
+ DWORD m_cbBitmapInfo[NUM_FILES]; // Size of the bitmap headers
+
+ // File opening variables
+ HANDLE m_hFile[NUM_FILES]; // Handles returned from CreateFile
+ BYTE * m_pFile[NUM_FILES]; // Points to beginning of file buffers
+ BYTE * m_pImage[NUM_FILES]; // Points to pixel bits
+ BOOL m_bFilesLoaded;
+
+ int m_iCurrentBitmap; // Which bitmap is being displayed
+ int m_iFrameNumber; // How many frames have been displayed
+ const REFERENCE_TIME m_rtFrameLength; // Duration of one frame
+
+ CCritSec m_cSharedState; // Protects our internal state
+ CImageDisplay m_Display; // Figures out our media type for us
+
+public:
+
+ CPushPinBitmapSet(HRESULT *phr, CSource *pFilter);
+ ~CPushPinBitmapSet();
+
+ // Override the version that offers exactly one media type
+ HRESULT GetMediaType(CMediaType *pMediaType);
+ HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest);
+ HRESULT FillBuffer(IMediaSample *pSample);
+
+ // Quality control
+ // Not implemented because we aren't going in real time.
+ // If the file-writing filter slows the graph down, we just do nothing, which means
+ // wait until we're unblocked. No frames are ever dropped.
+ STDMETHODIMP Notify(IBaseFilter *pSelf, Quality q)
+ {
+ return E_FAIL;
+ }
+
+};
+
+
+class CPushPinDesktop : public CSourceStream
+{
+protected:
+
+ int m_FramesWritten; // To track where we are in the file
+ BOOL m_bZeroMemory; // Do we need to clear the buffer?
+ CRefTime m_rtSampleTime; // The time stamp for each sample
+
+ int m_iFrameNumber;
+ const REFERENCE_TIME m_rtFrameLength;
+
+ RECT m_rScreen; // Rect containing entire screen coordinates
+
+ int m_iImageHeight; // The current image height
+ int m_iImageWidth; // And current image width
+ int m_iRepeatTime; // Time in msec between frames
+ int m_nCurrentBitDepth; // Screen bit depth
+
+ CMediaType m_MediaType;
+ CCritSec m_cSharedState; // Protects our internal state
+ CImageDisplay m_Display; // Figures out our media type for us
+
+ HWND m_hSrcHwnd; // Handle to the window to grab
+
+public:
+
+ CPushPinDesktop(HRESULT *phr, CSource *pFilter);
+ ~CPushPinDesktop();
+
+ // Override the version that offers exactly one media type
+ HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest);
+ HRESULT FillBuffer(IMediaSample *pSample);
+
+ // Set the agreed media type and set up the necessary parameters
+ HRESULT SetMediaType(const CMediaType *pMediaType);
+
+ // Support multiple display formats
+ HRESULT CheckMediaType(const CMediaType *pMediaType);
+ HRESULT GetMediaType(int iPosition, CMediaType *pmt);
+
+ // Quality control
+ // Not implemented because we aren't going in real time.
+ // If the file-writing filter slows the graph down, we just do nothing, which means
+ // wait until we're unblocked. No frames are ever dropped.
+ STDMETHODIMP Notify(IBaseFilter *pSelf, Quality q)
+ {
+ return E_FAIL;
+ }
+
+ HRESULT SetSrcHwnd(HWND hWnd)
+ {
+ m_hSrcHwnd = hWnd;
+ return S_OK;
+ }
+
+};
+
+
+
+class CPushSourceBitmap : public CSource
+{
+
+private:
+ // Constructor is private because you have to use CreateInstance
+ CPushSourceBitmap(IUnknown *pUnk, HRESULT *phr);
+ ~CPushSourceBitmap();
+
+ CPushPinBitmap *m_pPin;
+
+public:
+ static CUnknown * WINAPI CreateInstance(IUnknown *pUnk, HRESULT *phr);
+
+};
+
+
+class CPushSourceBitmapSet : public CSource
+{
+
+private:
+ // Constructor is private because you have to use CreateInstance
+ CPushSourceBitmapSet(IUnknown *pUnk, HRESULT *phr);
+ ~CPushSourceBitmapSet();
+
+ CPushPinBitmapSet *m_pPin;
+
+public:
+ static CUnknown * WINAPI CreateInstance(IUnknown *pUnk, HRESULT *phr);
+
+};
+
+
+class CPushSourceDesktop : public CSource
+{
+
+private:
+ // Constructor is private because you have to use CreateInstance
+ CPushSourceDesktop(IUnknown *pUnk, HRESULT *phr);
+ ~CPushSourceDesktop();
+
+ CPushPinDesktop *m_pPin;
+
+public:
+ static CUnknown * WINAPI CreateInstance(IUnknown *pUnk, HRESULT *phr);
+ DECLARE_IUNKNOWN;
+
+ HRESULT SetSrcHwnd(HWND hWnd);
+};
+
+
+#endif /* PLUGIN_DSHOW_DSPUSHSOURCE_H */
diff --git a/plugins/pluginDirectShow/internals/DSPushSourceDesktop.cxx b/plugins/pluginDirectShow/internals/DSPushSourceDesktop.cxx
new file mode 100644
index 0000000..1bdee9e
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSPushSourceDesktop.cxx
@@ -0,0 +1,434 @@
+#if !defined(_WIN32_WCE)
+//------------------------------------------------------------------------------
+// File: PushSourceDesktop.cpp
+//
+// Desc: DirectShow sample code - In-memory push mode source filter
+// Provides an image of the user's desktop as a continuously updating stream.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------------------------
+
+#include <streams.h>
+
+#include "DSPushSource.h"
+#include "DSDibHelper.h"
+#include "DSUtils.h"
+
+
+/**********************************************
+ *
+ * CPushPinDesktop Class
+ *
+ *
+ **********************************************/
+
+CPushPinDesktop::CPushPinDesktop(HRESULT *phr, CSource *pFilter)
+ : CSourceStream(NAME("Push Source Desktop"), phr, pFilter, L"Out"),
+ m_FramesWritten(0),
+ m_bZeroMemory(0),
+ m_iFrameNumber(0),
+ m_rtFrameLength(FPS_5), // Capture and display desktop 5 times per second
+ m_nCurrentBitDepth(24),
+ m_hSrcHwnd(NULL)
+{
+ // The main point of this sample is to demonstrate how to take a DIB
+ // in host memory and insert it into a video stream.
+
+ // To keep this sample as simple as possible, we just read the desktop image
+ // from a file and copy it into every frame that we send downstream.
+ //
+ // In the filter graph, we connect this filter to the AVI Mux, which creates
+ // the AVI file with the video frames we pass to it. In this case,
+ // the end result is a screen capture video (GDI images only, with no
+ // support for overlay surfaces).
+
+ // Get the device context of the main display
+ HDC hDC;
+ hDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
+
+ // Get the dimensions of the main desktop window
+ m_rScreen.left = m_rScreen.top = 0;
+ m_rScreen.right = GetDeviceCaps(hDC, HORZRES);
+ m_rScreen.bottom = GetDeviceCaps(hDC, VERTRES);
+
+ // Save dimensions for later use in FillBuffer()
+ m_iImageWidth = m_rScreen.right - m_rScreen.left;
+ m_iImageHeight = m_rScreen.bottom - m_rScreen.top;
+
+ // Release the device context
+ DeleteDC(hDC);
+}
+
+CPushPinDesktop::~CPushPinDesktop()
+{
+ DbgLog((LOG_TRACE, 3, TEXT("Frames written %d"), m_iFrameNumber));
+}
+
+
+//
+// GetMediaType
+//
+// Prefer 5 formats - 8, 16 (*2), 24 or 32 bits per pixel
+//
+// Prefered types should be ordered by quality, with zero as highest quality.
+// Therefore, iPosition =
+// 0 Return a 32bit mediatype
+// 1 Return a 24bit mediatype
+// 2 Return 16bit RGB565
+// 3 Return a 16bit mediatype (rgb555)
+// 4 Return 8 bit palettised format
+// >4 Invalid
+//
+HRESULT CPushPinDesktop::GetMediaType(int iPosition, CMediaType *pmt)
+{
+ CheckPointer(pmt,E_POINTER);
+ CAutoLock cAutoLock(m_pFilter->pStateLock());
+
+ if(iPosition < 0)
+ return E_INVALIDARG;
+
+ // Have we run off the end of types?
+ if(iPosition > 4)
+ return VFW_S_NO_MORE_ITEMS;
+
+ VIDEOINFO *pvi = (VIDEOINFO *) pmt->AllocFormatBuffer(sizeof(VIDEOINFO));
+ if(NULL == pvi)
+ return(E_OUTOFMEMORY);
+
+ // Initialize the VideoInfo structure before configuring its members
+ ZeroMemory(pvi, sizeof(VIDEOINFO));
+
+ switch(iPosition)
+ {
+ case 0:
+ {
+ // Return our highest quality 32bit format
+
+ // Since we use RGB888 (the default for 32 bit), there is
+ // no reason to use BI_BITFIELDS to specify the RGB
+ // masks. Also, not everything supports BI_BITFIELDS
+ pvi->bmiHeader.biCompression = BI_RGB;
+ pvi->bmiHeader.biBitCount = 32;
+ break;
+ }
+
+ case 1:
+ { // Return our 24bit format
+ pvi->bmiHeader.biCompression = BI_RGB;
+ pvi->bmiHeader.biBitCount = 24;
+ break;
+ }
+
+ case 2:
+ {
+ // 16 bit per pixel RGB565
+
+ // Place the RGB masks as the first 3 doublewords in the palette area
+ for(int i = 0; i < 3; i++)
+ pvi->TrueColorInfo.dwBitMasks[i] = bits565[i];
+
+ pvi->bmiHeader.biCompression = BI_BITFIELDS;
+ pvi->bmiHeader.biBitCount = 16;
+ break;
+ }
+
+ case 3:
+ { // 16 bits per pixel RGB555
+
+ // Place the RGB masks as the first 3 doublewords in the palette area
+ for(int i = 0; i < 3; i++)
+ pvi->TrueColorInfo.dwBitMasks[i] = bits555[i];
+
+ pvi->bmiHeader.biCompression = BI_BITFIELDS;
+ pvi->bmiHeader.biBitCount = 16;
+ break;
+ }
+
+ case 4:
+ { // 8 bit palettised
+
+ pvi->bmiHeader.biCompression = BI_RGB;
+ pvi->bmiHeader.biBitCount = 8;
+ pvi->bmiHeader.biClrUsed = iPALETTE_COLORS;
+ break;
+ }
+ }
+
+ // Adjust the parameters common to all formats
+ pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pvi->bmiHeader.biWidth = m_iImageWidth;
+ pvi->bmiHeader.biHeight = m_iImageHeight;
+ pvi->bmiHeader.biPlanes = 1;
+ pvi->bmiHeader.biSizeImage = GetBitmapSize(&pvi->bmiHeader);
+ pvi->bmiHeader.biClrImportant = 0;
+
+ SetRectEmpty(&(pvi->rcSource)); // we want the whole image area rendered.
+ SetRectEmpty(&(pvi->rcTarget)); // no particular destination rectangle
+
+ pmt->SetType(&MEDIATYPE_Video);
+ pmt->SetFormatType(&FORMAT_VideoInfo);
+ pmt->SetTemporalCompression(FALSE);
+
+ // Work out the GUID for the subtype from the header info.
+ const GUID SubTypeGUID = GetBitmapSubtype(&pvi->bmiHeader);
+ pmt->SetSubtype(&SubTypeGUID);
+ pmt->SetSampleSize(pvi->bmiHeader.biSizeImage);
+
+ return NOERROR;
+
+} // GetMediaType
+
+
+//
+// CheckMediaType
+//
+// We will accept 8, 16, 24 or 32 bit video formats, in any
+// image size that gives room to bounce.
+// Returns E_INVALIDARG if the mediatype is not acceptable
+//
+HRESULT CPushPinDesktop::CheckMediaType(const CMediaType *pMediaType)
+{
+ CheckPointer(pMediaType,E_POINTER);
+
+ if((*(pMediaType->Type()) != MEDIATYPE_Video) || // we only output video
+ !(pMediaType->IsFixedSize())) // in fixed size samples
+ {
+ return E_INVALIDARG;
+ }
+
+ // Check for the subtypes we support
+ const GUID *SubType = pMediaType->Subtype();
+ if (SubType == NULL)
+ return E_INVALIDARG;
+
+ if( (*SubType != MEDIASUBTYPE_RGB24)
+#if 0
+ && (*SubType != MEDIASUBTYPE_RGB565)
+ && (*SubType != MEDIASUBTYPE_RGB555)
+ && (*SubType != MEDIASUBTYPE_RGB32)
+ && (*SubType != MEDIASUBTYPE_RGB8)
+#endif
+ )
+ {
+ return E_INVALIDARG;
+ }
+
+ // Get the format area of the media type
+ VIDEOINFO *pvi = (VIDEOINFO *) pMediaType->Format();
+
+ if(pvi == NULL)
+ return E_INVALIDARG;
+
+ // Check if the image width & height have changed
+ if( pvi->bmiHeader.biWidth != m_iImageWidth ||
+ abs(pvi->bmiHeader.biHeight) != m_iImageHeight)
+ {
+ // If the image width/height is changed, fail CheckMediaType() to force
+ // the renderer to resize the image.
+ return E_INVALIDARG;
+ }
+
+ // Don't accept formats with negative height, which would cause the desktop
+ // image to be displayed upside down.
+ if (pvi->bmiHeader.biHeight < 0)
+ return E_INVALIDARG;
+
+ return S_OK; // This format is acceptable.
+
+} // CheckMediaType
+
+
+//
+// DecideBufferSize
+//
+// This will always be called after the format has been sucessfully
+// negotiated. So we have a look at m_mt to see what size image we agreed.
+// Then we can ask for buffers of the correct size to contain them.
+//
+HRESULT CPushPinDesktop::DecideBufferSize(IMemAllocator *pAlloc,
+ ALLOCATOR_PROPERTIES *pProperties)
+{
+ CheckPointer(pAlloc,E_POINTER);
+ CheckPointer(pProperties,E_POINTER);
+
+ CAutoLock cAutoLock(m_pFilter->pStateLock());
+ HRESULT hr = NOERROR;
+
+ VIDEOINFO *pvi = (VIDEOINFO *) m_mt.Format();
+ pProperties->cBuffers = 1;
+ pProperties->cbBuffer = pvi->bmiHeader.biSizeImage;
+
+ ASSERT(pProperties->cbBuffer);
+
+ // Ask the allocator to reserve us some sample memory. NOTE: the function
+ // can succeed (return NOERROR) but still not have allocated the
+ // memory that we requested, so we must check we got whatever we wanted.
+ ALLOCATOR_PROPERTIES Actual;
+ hr = pAlloc->SetProperties(pProperties,&Actual);
+ if(FAILED(hr))
+ {
+ return hr;
+ }
+
+ // Is this allocator unsuitable?
+ if(Actual.cbBuffer < pProperties->cbBuffer)
+ {
+ return E_FAIL;
+ }
+
+ // Make sure that we have only 1 buffer (we erase the ball in the
+ // old buffer to save having to zero a 200k+ buffer every time
+ // we draw a frame)
+ ASSERT(Actual.cBuffers == 1);
+ return NOERROR;
+
+} // DecideBufferSize
+
+
+//
+// SetMediaType
+//
+// Called when a media type is agreed between filters
+//
+HRESULT CPushPinDesktop::SetMediaType(const CMediaType *pMediaType)
+{
+ CAutoLock cAutoLock(m_pFilter->pStateLock());
+
+ // Pass the call up to my base class
+ HRESULT hr = CSourceStream::SetMediaType(pMediaType);
+
+ if(SUCCEEDED(hr))
+ {
+ VIDEOINFO * pvi = (VIDEOINFO *) m_mt.Format();
+ if (pvi == NULL)
+ return E_UNEXPECTED;
+
+ switch(pvi->bmiHeader.biBitCount)
+ {
+ case 8: // 8-bit palettized
+ case 16: // RGB565, RGB555
+ case 24: // RGB24
+ case 32: // RGB32
+ // Save the current media type and bit depth
+ m_MediaType = *pMediaType;
+ m_nCurrentBitDepth = pvi->bmiHeader.biBitCount;
+ hr = S_OK;
+ break;
+
+ default:
+ // We should never agree any other media types
+ ASSERT(FALSE);
+ hr = E_INVALIDARG;
+ break;
+ }
+ }
+
+ return hr;
+
+} // SetMediaType
+
+
+// This is where we insert the DIB bits into the video stream.
+// FillBuffer is called once for every sample in the stream.
+HRESULT CPushPinDesktop::FillBuffer(IMediaSample *pSample)
+{
+ BYTE *pData;
+ long cbData;
+
+ CheckPointer(pSample, E_POINTER);
+
+ CAutoLock cAutoLockShared(&m_cSharedState);
+
+ // Access the sample's data buffer
+ pSample->GetPointer(&pData);
+ cbData = pSample->GetSize();
+
+ // Check that we're still using video
+ ASSERT(m_mt.formattype == FORMAT_VideoInfo);
+
+ VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)m_mt.pbFormat;
+
+ // Copy the DIB bits over into our filter's output buffer.
+ // Since sample size may be larger than the image size, bound the copy size.
+ int nSize = min(pVih->bmiHeader.biSizeImage, (DWORD) cbData);
+ HDIB hDib = CopyScreenToBitmap(&m_rScreen, pData, (BITMAPINFO *) &(pVih->bmiHeader));
+
+ if (hDib)
+ DeleteObject(hDib);
+
+ // Set the timestamps that will govern playback frame rate.
+ // If this file is getting written out as an AVI,
+ // then you'll also need to configure the AVI Mux filter to
+ // set the Average Time Per Frame for the AVI Header.
+ // The current time is the sample's start.
+ REFERENCE_TIME rtStart = m_iFrameNumber * m_rtFrameLength;
+ REFERENCE_TIME rtStop = rtStart + m_rtFrameLength;
+
+ pSample->SetTime(&rtStart, &rtStop);
+ m_iFrameNumber++;
+
+ // Set TRUE on every sample for uncompressed frames
+ pSample->SetSyncPoint(TRUE);
+
+ return S_OK;
+}
+
+
+
+/**********************************************
+ *
+ * CPushSourceDesktop Class
+ *
+ **********************************************/
+
+CPushSourceDesktop::CPushSourceDesktop(IUnknown *pUnk, HRESULT *phr)
+ : CSource(NAME("PushSourceDesktop"), pUnk, CLSID_PushSourceDesktop)
+{
+ // The pin magically adds itself to our pin array.
+ m_pPin = new CPushPinDesktop(phr, this);
+
+ if (phr)
+ {
+ if (m_pPin == NULL)
+ *phr = E_OUTOFMEMORY;
+ else
+ *phr = S_OK;
+ }
+}
+
+
+CPushSourceDesktop::~CPushSourceDesktop()
+{
+ if (m_pPin)
+ {
+ delete m_pPin;
+ m_pPin = NULL;
+ }
+}
+
+
+CUnknown * WINAPI CPushSourceDesktop::CreateInstance(IUnknown *pUnk, HRESULT *phr)
+{
+ CPushSourceDesktop *pNewFilter = new CPushSourceDesktop(pUnk, phr );
+
+ if (phr)
+ {
+ if (pNewFilter == NULL)
+ *phr = E_OUTOFMEMORY;
+ else
+ *phr = S_OK;
+ }
+ return pNewFilter;
+
+}
+
+HRESULT CPushSourceDesktop::SetSrcHwnd(HWND hWnd)
+{
+ if (m_pPin)
+ {
+ return m_pPin->SetSrcHwnd(hWnd);
+ }
+ return E_FAIL;
+}
+
+#endif /* _WIN32_WCE */
diff --git a/plugins/pluginDirectShow/internals/DSScreenCastGraph.cxx b/plugins/pluginDirectShow/internals/DSScreenCastGraph.cxx
new file mode 100644
index 0000000..b425d65
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSScreenCastGraph.cxx
@@ -0,0 +1,257 @@
+#if !defined(_WIN32_WCE)
+/* Copyright (C) 2014 Mamadou DIOP
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#include <streams.h>
+#include "internals/DSScreenCastGraph.h"
+#include "internals/DSPushSource.h"
+#include "internals/DSUtils.h"
+#include "internals/DSCaptureUtils.h"
+
+#include "tsk_debug.h"
+
+#include <iostream>
+
+using namespace std;
+
+DSScreenCastGraph::DSScreenCastGraph(ISampleGrabberCB* callback, HRESULT *hr)
+: DSBaseCaptureGraph(callback, hr)
+{
+ this->grabberCallback = callback;
+
+ this->captureFormat = NULL;
+ this->captureGraphBuilder = NULL;
+ this->graphBuilder = NULL;
+
+ this->sourceFilter = NULL;
+ this->sampleGrabberFilter = NULL;
+
+ this->nullRendererFilter = NULL;
+ this->grabberController = NULL;
+ this->mediaController = NULL;
+ this->mediaEventController = NULL;
+
+ this->running = FALSE;
+ this->paused = FALSE;
+
+ *hr = this->createCaptureGraph();
+}
+
+DSScreenCastGraph::~DSScreenCastGraph()
+{
+ SAFE_RELEASE(this->mediaEventController);
+ SAFE_RELEASE(this->mediaController);
+ SAFE_RELEASE(this->grabberController);
+
+ SAFE_RELEASE(this->nullRendererFilter);
+ SAFE_RELEASE(this->sampleGrabberFilter);
+
+ SAFE_RELEASE(this->graphBuilder);
+ SAFE_RELEASE(this->captureGraphBuilder);
+
+ SAFE_RELEASE(this->sourceFilter);
+}
+
+HRESULT DSScreenCastGraph::setParameters(DSCaptureFormat *format, int framerate)
+{
+ return S_OK;
+}
+
+#ifdef _WIN32_WCE
+# include <tinydshow/wce/DSInxbNullFilter.h>
+#endif
+
+HRESULT DSScreenCastGraph::connect()
+{
+ HRESULT hr;
+
+ if (!this->sourceFilter){
+ TSK_DEBUG_ERROR("Invalid source filter");
+ return E_FAIL;
+ }
+#if 0
+ if (!this->captureFormat){
+ TSK_DEBUG_ERROR("Invalid capture format");
+ return E_FAIL;
+ }
+#endif
+
+ hr = ConnectFilters(this->graphBuilder, this->sourceFilter, this->sampleGrabberFilter); if(FAILED(hr)) { TSK_DEBUG_ERROR("ConnectFilters failed"); return hr; }
+ hr = ConnectFilters(this->graphBuilder, this->sampleGrabberFilter, this->nullRendererFilter); if(FAILED(hr)) { TSK_DEBUG_ERROR("ConnectFilters failed"); return hr; }
+
+ return hr;
+}
+
+HRESULT DSScreenCastGraph::disconnect()
+{
+ HRESULT hr;
+
+ if (!this->sourceFilter)
+ {
+ return E_FAIL;
+ }
+#if 0
+ if (!this->captureFormat)
+ {
+ return E_FAIL;
+ }
+#endif
+
+ hr = DisconnectFilters(this->graphBuilder, this->sourceFilter, this->sampleGrabberFilter);
+ hr = DisconnectFilters(this->graphBuilder, this->sampleGrabberFilter, this->nullRendererFilter);
+
+ return hr;
+}
+
+HRESULT DSScreenCastGraph::start()
+{
+ HRESULT hr;
+
+ if (isRunning() && !isPaused())
+ {
+ return S_OK;
+ }
+
+ hr = this->mediaController->Run();
+ if (!SUCCEEDED(hr))
+ {
+ TSK_DEBUG_ERROR("DSScreenCastGraph::mediaController->Run() has failed with %ld", hr);
+ return hr;
+ }
+ this->running = true;
+ return hr;
+}
+
+HRESULT DSScreenCastGraph::pause()
+{
+ HRESULT hr = S_OK;
+ if (isRunning())
+ {
+ hr = this->mediaController->Pause();
+ if (SUCCEEDED(hr))
+ {
+ this->paused = TRUE;
+ }
+ }
+ return hr;
+}
+
+HRESULT DSScreenCastGraph::stop()
+{
+ if (!this->running)
+ {
+ return S_OK;
+ }
+
+ HRESULT hr;
+ hr = this->mediaController->Stop();
+ if (FAILED(hr))
+ {
+ TSK_DEBUG_ERROR("DSScreenCastGraph::mediaController->Stop() has failed with %ld", hr);
+ }
+ this->running = false;
+ this->paused = false;
+ return hr;
+}
+
+bool DSScreenCastGraph::isRunning()
+{
+ return this->running;
+}
+
+bool DSScreenCastGraph::isPaused()
+{
+ return this->paused;
+}
+
+HRESULT DSScreenCastGraph::getConnectedMediaType(AM_MEDIA_TYPE *mediaType)
+{
+ return this->grabberController->GetConnectedMediaType(mediaType);
+}
+
+HRESULT DSScreenCastGraph::createCaptureGraph()
+{
+ HRESULT hr;
+
+ // Create capture graph builder
+ hr = COCREATE(CLSID_CaptureGraphBuilder2, IID_ICaptureGraphBuilder2, this->captureGraphBuilder);
+ if(FAILED(hr)) return hr;
+
+ // Create the graph builder
+ hr = COCREATE(CLSID_FilterGraph, IID_IGraphBuilder, this->graphBuilder);
+ if(FAILED(hr)) return hr;
+
+ // Initialize the Capture Graph Builder.
+ hr = this->captureGraphBuilder->SetFiltergraph(this->graphBuilder);
+ if(FAILED(hr)) return hr;
+
+ // Create source filter
+ LPUNKNOWN pUnk = NULL;
+ this->sourceFilter = (CPushSourceDesktop*)CPushSourceDesktop::CreateInstance(pUnk, &hr);
+ if(FAILED(hr)) return hr;
+ this->sourceFilter->AddRef();
+
+ // Create the sample grabber filter
+ hr = COCREATE(CLSID_SampleGrabber, IID_IBaseFilter, this->sampleGrabberFilter);
+ if(FAILED(hr)) return hr;
+
+ // Create the NULL renderer
+ hr = COCREATE(CLSID_NullRenderer, IID_IBaseFilter, this->nullRendererFilter);
+ if(FAILED(hr)) return hr;
+
+ // Add source filter to the graph
+ hr = this->graphBuilder->AddFilter(this->sourceFilter, FILTER_SCREENCAST);
+ if(FAILED(hr)) return hr;
+
+ // Add sample grabber to the graph
+ hr = this->graphBuilder->AddFilter(this->sampleGrabberFilter, FITLER_SAMPLE_GRABBER);
+ if(FAILED(hr)) return hr;
+
+ // Add null renderer to the graph
+ hr = this->graphBuilder->AddFilter(this->nullRendererFilter, FILTER_NULL_RENDERER);
+ if(FAILED(hr)) return hr;
+
+ // Find media control
+ hr = QUERY(this->graphBuilder, IID_IMediaControl, this->mediaController);
+ if(FAILED(hr)) return hr;
+
+ // Create the sample grabber controller
+ hr = QUERY(this->sampleGrabberFilter, IID_ISampleGrabber, this->grabberController);
+ if(FAILED(hr)) return hr;
+
+ // Set the sample grabber media type (RGB24)
+ // TODO : CHECK
+ AM_MEDIA_TYPE mt;
+ ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
+ mt.majortype = MEDIATYPE_Video;
+ mt.subtype = MEDIASUBTYPE_RGB24;
+ mt.formattype = FORMAT_VideoInfo;
+
+ hr = this->grabberController->SetMediaType(&mt);
+ if(FAILED(hr)) return hr;
+
+ // Set sample grabber media type
+ this->grabberController->SetOneShot(FALSE);
+ this->grabberController->SetBufferSamples(FALSE);
+
+ hr = this->grabberController->SetCallback(this->grabberCallback, 1);
+ if(FAILED(hr)) return hr;
+
+ return hr;
+}
+
+#endif /* _WIN32_WCE */ \ No newline at end of file
diff --git a/plugins/pluginDirectShow/internals/DSScreenCastGraph.h b/plugins/pluginDirectShow/internals/DSScreenCastGraph.h
new file mode 100644
index 0000000..d201668
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSScreenCastGraph.h
@@ -0,0 +1,160 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#ifndef PLUGIN_DSHOW_DSSCREENCAST_H
+#define PLUGIN_DSHOW_DSSCREENCAST_H
+
+#include "plugin_dshow_config.h"
+#include "internals/DSBaseCaptureGraph.h"
+
+#include <control.h>
+#include <vector>
+#include <qedit.h>
+
+
+class CPushSourceDesktop;
+
+class DSScreenCastGraph : public DSBaseCaptureGraph
+{
+public:
+ DSScreenCastGraph(ISampleGrabberCB* callback, HRESULT *hr);
+ virtual ~DSScreenCastGraph();
+
+ std::vector<DSCaptureFormat> *getFormats() { return &this->supportedFormats; };
+
+ virtual HRESULT setSource(const std::string &devicePath) { return S_OK; }
+ HRESULT setParameters(DSCaptureFormat *format, int framerate);
+
+ HRESULT connect();
+ HRESULT disconnect();
+
+ HRESULT start();
+ HRESULT stop();
+ HRESULT pause();
+ bool isRunning();
+ bool isPaused();
+
+ HRESULT getConnectedMediaType(AM_MEDIA_TYPE *mediaType);
+
+ virtual std::string getDeviceId() const { return std::string("screencast"); }
+
+private:
+ HRESULT createCaptureGraph();
+
+private:
+ ISampleGrabberCB *grabberCallback;
+
+ ICaptureGraphBuilder2 *captureGraphBuilder;
+ IGraphBuilder *graphBuilder;
+
+ CPushSourceDesktop *sourceFilter;
+ IBaseFilter *nullRendererFilter;
+ IBaseFilter *sampleGrabberFilter;
+
+ ISampleGrabber *grabberController;
+
+ IMediaControl *mediaController;
+ IMediaEventEx *mediaEventController;
+
+ std::vector<DSCaptureFormat> supportedFormats;
+ DSCaptureFormat *captureFormat;
+
+ bool running;
+ bool paused;
+};
+
+#endif /* PLUGIN_DSHOW_DSSCREENCAST_H */
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#ifndef PLUGIN_DSHOW_DSSCREENCAST_H
+#define PLUGIN_DSHOW_DSSCREENCAST_H
+
+#include "plugin_dshow_config.h"
+#include "internals/DSBaseCaptureGraph.h"
+
+#include <control.h>
+#include <vector>
+#include <qedit.h>
+
+
+class CPushSourceDesktop;
+
+class DSScreenCastGraph : public DSBaseCaptureGraph
+{
+public:
+ DSScreenCastGraph(ISampleGrabberCB* callback, HRESULT *hr);
+ virtual ~DSScreenCastGraph();
+
+ std::vector<DSCaptureFormat> *getFormats() { return &this->supportedFormats; };
+
+ virtual HRESULT setSource(const std::string &devicePath) { return S_OK; }
+ HRESULT setParameters(DSCaptureFormat *format, int framerate);
+
+ HRESULT connect();
+ HRESULT disconnect();
+
+ HRESULT start();
+ HRESULT stop();
+ HRESULT pause();
+ bool isRunning();
+ bool isPaused();
+
+ HRESULT getConnectedMediaType(AM_MEDIA_TYPE *mediaType);
+
+ virtual std::string getDeviceId() const { return std::string("screencast"); }
+
+private:
+ HRESULT createCaptureGraph();
+
+private:
+ ISampleGrabberCB *grabberCallback;
+
+ ICaptureGraphBuilder2 *captureGraphBuilder;
+ IGraphBuilder *graphBuilder;
+
+ CPushSourceDesktop *sourceFilter;
+ IBaseFilter *nullRendererFilter;
+ IBaseFilter *sampleGrabberFilter;
+
+ ISampleGrabber *grabberController;
+
+ IMediaControl *mediaController;
+ IMediaEventEx *mediaEventController;
+
+ std::vector<DSCaptureFormat> supportedFormats;
+ DSCaptureFormat *captureFormat;
+
+ bool running;
+ bool paused;
+};
+
+#endif /* PLUGIN_DSHOW_DSSCREENCAST_H */
diff --git a/plugins/pluginDirectShow/internals/DSUtils.cxx b/plugins/pluginDirectShow/internals/DSUtils.cxx
new file mode 100644
index 0000000..913c081
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSUtils.cxx
@@ -0,0 +1,365 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#include "internals/DSUtils.h"
+
+#if defined (_WIN32_WCE)
+#include <atlbase.h>
+#include <atlstr.h>
+#else
+#include <atlconv.h>
+#include <d3d9.h>
+#endif
+
+#include "tsk_debug.h"
+
+HWND GetMainWindow()
+{
+ HWND hWnd;
+ if (!(hWnd = GetActiveWindow())) {
+ if (!(hWnd = GetForegroundWindow())) {
+#if !defined(_WIN32_WCE)
+ if (!(hWnd = GetConsoleWindow())) {
+ return NULL;
+ }
+#endif
+ }
+ }
+ return hWnd;
+}
+
+bool IsMainThread()
+{
+ HWND hWnd = GetMainWindow();
+ if (hWnd) {
+ DWORD mainTid = GetWindowThreadProcessId(hWnd, NULL);
+ DWORD currentTid = GetCurrentThreadId();
+ return (mainTid == currentTid);
+ }
+ return false;
+}
+
+bool IsD3D9Supported()
+{
+#if defined(_WIN32_WCE)
+ return false;
+#else
+ static bool g_bChecked = false;
+ static bool g_bSupported = false;
+
+ if (g_bChecked) {
+ return g_bSupported;
+ }
+ g_bChecked = true;
+ HRESULT hr = S_OK;
+ IDirect3D9* pD3D = NULL;
+ D3DDISPLAYMODE mode = { 0 };
+ D3DPRESENT_PARAMETERS pp = {0};
+ IDirect3DDevice9* pDevice = NULL;
+
+ if (!(pD3D = Direct3DCreate9(D3D_SDK_VERSION))) {
+ hr = E_OUTOFMEMORY;
+ goto bail;
+ }
+
+ hr = pD3D->GetAdapterDisplayMode(
+ D3DADAPTER_DEFAULT,
+ &mode
+ );
+ if (FAILED(hr)) {
+ goto bail;
+ }
+
+ hr = pD3D->CheckDeviceType(
+ D3DADAPTER_DEFAULT,
+ D3DDEVTYPE_HAL,
+ mode.Format,
+ D3DFMT_X8R8G8B8,
+ TRUE // windowed
+ );
+ if (FAILED(hr)) {
+ goto bail;
+ }
+ pp.BackBufferFormat = D3DFMT_X8R8G8B8;
+ pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+ pp.Windowed = TRUE;
+ pp.hDeviceWindow = GetDesktopWindow();
+ hr = pD3D->CreateDevice(
+ D3DADAPTER_DEFAULT,
+ D3DDEVTYPE_HAL,
+ pp.hDeviceWindow,
+ D3DCREATE_HARDWARE_VERTEXPROCESSING,
+ &pp,
+ &pDevice
+ );
+ if (FAILED(hr)) {
+ goto bail;
+ }
+
+ // Everythings is OK
+ g_bSupported = true;
+ TSK_DEBUG_INFO("D3D9 supported");
+
+bail:
+ if (!g_bSupported) {
+ TSK_DEBUG_WARN("D3D9 not supported");
+ }
+ SAFE_RELEASE(pDevice);
+ SAFE_RELEASE(pD3D);
+ return g_bSupported;
+#endif /* _WIN32_WCE */
+}
+
+IPin *GetPin(IBaseFilter *filter, PIN_DIRECTION direction)
+{
+ IEnumPins *enumPins = NULL;
+ IPin *pin = NULL;
+
+ HRESULT hr = filter->EnumPins(&enumPins);
+ if(!enumPins){
+ return NULL;
+ }
+
+ for(;;){
+ ULONG fetched = 0;
+ PIN_DIRECTION pinDir = PIN_DIRECTION(-1);
+ pin = NULL;
+
+ if (FAILED(enumPins->Next(1, &pin, &fetched))){
+ enumPins->Release();
+ return NULL;
+ }
+
+ if (fetched == 1 && pin){
+ pin->QueryDirection(&pinDir);
+ if(pinDir == direction){
+ break;
+ }
+ pin->Release();
+ }
+ }
+
+ enumPins->Release();
+ return pin;
+}
+
+HRESULT ConnectFilters(IGraphBuilder *graphBuilder, IBaseFilter *source, IBaseFilter *destination, AM_MEDIA_TYPE *mediaType)
+{
+ HRESULT hr;
+
+ IPin *outPin = GetPin(source, PINDIR_OUTPUT);
+ IPin *inPin = GetPin(destination, PINDIR_INPUT);
+
+ if (mediaType != NULL){
+ hr = graphBuilder->ConnectDirect(outPin, inPin, mediaType);
+ }
+ else{
+ hr = graphBuilder->Connect(outPin, inPin);
+ }
+
+ SAFE_RELEASE(outPin);
+ SAFE_RELEASE(inPin);
+
+ return hr;
+}
+
+HRESULT DisconnectFilters(IGraphBuilder *graphBuilder, IBaseFilter *source, IBaseFilter *destination)
+{
+ HRESULT hr;
+
+ IPin *outPin = GetPin(source, PINDIR_OUTPUT);
+ IPin *inPin = GetPin(destination, PINDIR_INPUT);
+
+ if (inPin){
+ hr = graphBuilder->Disconnect(inPin);
+ }
+
+ if (outPin){
+ hr = graphBuilder->Disconnect(outPin);
+ }
+
+ SAFE_RELEASE(outPin);
+ SAFE_RELEASE(inPin);
+
+ return hr;
+}
+
+bool DisconnectAllFilters(IGraphBuilder *graphBuilder)
+{
+ IEnumFilters* filterEnum = NULL;
+ IBaseFilter* currentFilter = NULL;
+ ULONG fetched;
+ HRESULT hr;
+
+ hr = graphBuilder->EnumFilters(&filterEnum);
+ if (FAILED(hr)) {
+ SAFE_RELEASE(filterEnum);
+ return false;
+ }
+
+ while(filterEnum->Next(1, &currentFilter, &fetched) == S_OK){
+ hr = DisconnectFilters(graphBuilder, currentFilter, currentFilter);
+ SAFE_RELEASE(currentFilter);
+ }
+ SAFE_RELEASE(filterEnum);
+ SAFE_RELEASE(currentFilter);
+ return true;
+}
+
+bool RemoveAllFilters(IGraphBuilder *graphBuilder)
+{
+ IEnumFilters* filterEnum = NULL;
+ IBaseFilter* currentFilter = NULL;
+ ULONG fetched;
+ HRESULT hr;
+
+ hr = graphBuilder->EnumFilters(&filterEnum);
+ if (FAILED(hr)) return false;
+
+ while(filterEnum->Next(1, &currentFilter, &fetched) == S_OK){
+ hr = graphBuilder->RemoveFilter(currentFilter);
+ if (FAILED(hr)){
+ SAFE_RELEASE(filterEnum);
+ return false;
+ }
+ SAFE_RELEASE(currentFilter);
+ filterEnum->Reset();
+ }
+
+ SAFE_RELEASE(filterEnum);
+ SAFE_RELEASE(currentFilter);
+ return true;
+}
+
+
+#include "internals/DSDisplay.h"
+#include "internals/DSGrabber.h"
+
+#define WM_CREATE_DISPLAY_ON_UI_THREAD (WM_USER + 101)
+#define WM_CREATE_GRABBER_ON_UI_THREAD (WM_CREATE_DISPLAY_ON_UI_THREAD + 1)
+#define WM_CREATE_ON_UI_THREAD_TIMEOUT 1000
+
+// C Callback that dispatch event to create display on UI thread
+static LRESULT CALLBACK __create__WndProcWindow(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ HANDLE* event = reinterpret_cast<HANDLE*>(wParam);
+ BOOL* isScreenCast = reinterpret_cast<BOOL*>(GetProp(hWnd, TEXT("screnCast")));
+
+ if(event && lParam){
+ switch(uMsg){
+ case WM_CREATE_DISPLAY_ON_UI_THREAD:
+ {
+ HRESULT hr;
+ DSDisplay** ppDisplay = reinterpret_cast<DSDisplay**>(lParam);
+ *ppDisplay = new DSDisplay(&hr);
+ SetEvent(event);
+ break;
+ }
+ case WM_CREATE_GRABBER_ON_UI_THREAD:
+ {
+ HRESULT hr;
+ DSGrabber** ppGrabber = reinterpret_cast<DSGrabber**>(lParam);
+ *ppGrabber = new DSGrabber(&hr, *isScreenCast);
+ SetEvent(event);
+ break;
+ }
+ }
+ }
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+int createOnCurrentThead(HWND hWnd, void** ppRet, BOOL display, BOOL screnCast)
+{
+ HRESULT hr;
+ if(display) *ppRet = new DSDisplay(&hr);
+ else *ppRet = new DSGrabber(&hr, screnCast);
+ if(FAILED(hr)){
+ TSK_DEBUG_ERROR("Failed to created DirectShow %s", display ? "Display" : "Grabber");
+ SAFE_DELETE_PTR(*ppRet);
+ return -2;
+ }
+ return 0;
+}
+
+int createOnUIThead(HWND hWnd, void** ppRet, BOOL display, BOOL screnCast)
+{
+ static BOOL __isScreenCastFalse = FALSE;
+ static BOOL __isScreenCastTrue = TRUE;
+ if(!ppRet){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if (IsMainThread()) {
+ return createOnCurrentThead(hWnd, ppRet, display, screnCast);
+ }
+ else{
+ TSK_DEBUG_INFO("Create DirectShow element on worker thread");
+ HANDLE event = NULL;
+ int ret = 0;
+ DWORD retWait, retryCount = 3;
+
+ if(!hWnd){
+ if (!(hWnd = FindWindow(NULL, TEXT("Boghe - IMS/RCS Client")))) {
+ if(!(hWnd = GetMainWindow())){
+ TSK_DEBUG_ERROR("No Window handle could be used");
+ return -2;
+ }
+ }
+ }
+#if defined(_WIN32_WCE)
+ WNDPROC wndProc = (WNDPROC) SetWindowLong(hWnd, GWL_WNDPROC, (LONG) __create__WndProcWindow);
+#else
+ WNDPROC wndProc = (WNDPROC) SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR) __create__WndProcWindow);
+#endif
+ if (!wndProc) {
+ TSK_DEBUG_ERROR("SetWindowLongPtr() failed with errcode=%d", GetLastError());
+ return createOnCurrentThead(hWnd, ppRet, display, screnCast);
+ }
+
+ if (!(event = CreateEvent(NULL, TRUE, FALSE, NULL))) {
+ TSK_DEBUG_ERROR("Failed to create new event");
+ ret = -4; goto bail;
+ }
+ SetProp(hWnd, TEXT("screnCast"), screnCast ? &__isScreenCastTrue : &__isScreenCastFalse);
+ if (!PostMessage(hWnd, display ? WM_CREATE_DISPLAY_ON_UI_THREAD : WM_CREATE_GRABBER_ON_UI_THREAD, reinterpret_cast<WPARAM>(event), reinterpret_cast<LPARAM>(ppRet))) {
+ TSK_DEBUG_ERROR("PostMessageA() failed");
+ ret = -5; goto bail;
+ }
+
+ do {
+ retWait = WaitForSingleObject(event, WM_CREATE_ON_UI_THREAD_TIMEOUT);
+ }
+ while (retryCount-- > 0 && (retWait == WAIT_TIMEOUT));
+
+ bail:
+ // restore
+ if (hWnd && wndProc) {
+#if defined(_WIN32_WCE)
+ SetWindowLong(hWnd, GWL_WNDPROC, (LONG)wndProc);
+#else
+ SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)wndProc);
+#endif
+ }
+ if (event) {
+ CloseHandle(event);
+ }
+
+ return ret;
+ }
+} \ No newline at end of file
diff --git a/plugins/pluginDirectShow/internals/DSUtils.h b/plugins/pluginDirectShow/internals/DSUtils.h
new file mode 100644
index 0000000..09690ea
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/DSUtils.h
@@ -0,0 +1,82 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#ifndef PLUGIN_DSHOW_DUTILS_H
+#define PLUGIN_DSHOW_DUTILS_H
+
+#include "plugin_dshow_config.h"
+
+#include <strmif.h>
+
+// --------------------------------------------------------------------------------
+
+#define SAFE_RELEASE(x) if ((x)) { (x)->Release(); (x) = NULL; }
+#define SAFE_DELETE_PTR(x) if ((x)) { delete (x); (x) = NULL; }
+#define SAFE_DELETE_ARRAY(x) if ((x)) { delete[] (x); (x) = NULL; }
+// In CHECK_HR(x) When (x) is a function it will be executed twice when used in "TSK_DEBUG_ERROR(x)" and "If(x)"
+#define CHECK_HR(x) { HRESULT __hr__ = (x); if (FAILED(__hr__)) { TSK_DEBUG_ERROR("Operation Failed (%08x)", __hr__); goto bail; } }
+
+#define DS_NANOS_TO_100NS(NANOS) (((LONGLONG)(NANOS)) / 100ui64)
+#define DS_MICROS_TO_100NS(MICROS) (((LONGLONG)(MICROS)) * 10ui64)
+#define DS_MILLIS_TO_100NS(MILLIS) (((LONGLONG)(MILLIS)) * 10000ui64)
+#define DS_SECONDS_TO_100NS(SEC) (((LONGLONG)(SEC)) * 10000000ui64)
+#define DS_SECONDS_FROM_100NS(SEC) (10000000ui64/(SEC))
+
+#define COCREATE(cls, iid, target) \
+ CoCreateInstance(cls, NULL, CLSCTX_INPROC_SERVER, iid, reinterpret_cast<void**>(&target))
+#define QUERY(source, iid, target) \
+ source->QueryInterface(iid, reinterpret_cast<void**>(&target))
+
+// --------------------------------------------------------------------------------
+
+
+#define FILTER_WEBCAM _T("WEBCAM")
+#define FILTER_SCREENCAST _T("SCREENCAST")
+#define FILTER_FRAMERATE _T("TDSHOW_FRAMERATE")
+#define FILTER_OUTPUT _T("TDSHOW_OUTPUT")
+#define FITLER_SAMPLE_GRABBER _T("SAMPLE_GRABBER")
+#define FILTER_AVI_DECOMPRESSOR _T("AVI_DECOMPRESSOR")
+
+#define FILTER_COLORSPACE_CONVERTOR _T("COLORSPACE_CONVERTOR")
+#define FILTER_NULL_RENDERER _T("NULL_RENDERER")
+#define FILTER_VIDEO_RENDERER _T("VIDEO_RENDERER")
+#define FILTER_VIDEO_MIXING_RENDERER _T("VIDEO_MIXING_RENDERER")
+#define FILTER_COLOR_CONVERTOR_565 _T("COLOR_CONVERTOR_565")
+
+// --------------------------------------------------------------------------------
+
+HWND GetMainWindow();
+
+bool IsMainThread();
+
+bool IsD3D9Supported();
+
+IPin *GetPin(IBaseFilter *pFilter, PIN_DIRECTION dir);
+
+HRESULT ConnectFilters(IGraphBuilder *graphBuilder, IBaseFilter *source, IBaseFilter *destination, AM_MEDIA_TYPE *mediaType = NULL);
+
+HRESULT DisconnectFilters(IGraphBuilder *graphBuilder, IBaseFilter *source, IBaseFilter *destination);
+
+bool DisconnectAllFilters(IGraphBuilder *graphBuilder);
+
+bool RemoveAllFilters(IGraphBuilder *graphBuilder);
+
+int createOnCurrentThead(HWND hWnd, void** ppRet, BOOL display, BOOL screnCast);
+
+int createOnUIThead(HWND hWnd, void** ppRet, BOOL display, BOOL screnCast);
+
+#endif /* PLUGIN_DSHOW_DUTILS_H */
diff --git a/plugins/pluginDirectShow/internals/Resizer.cxx b/plugins/pluginDirectShow/internals/Resizer.cxx
new file mode 100644
index 0000000..32bcfac
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/Resizer.cxx
@@ -0,0 +1,1192 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+/*
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ */
+#if !defined(RESIZER_DO_NOT_INCLUDE_HEADER)
+#include "internals/Resizer.h"
+#endif /* DO_NOT_INCLUDE_HEADER */
+
+
+/* stretch proportions */
+#define STRETCH_1_1 1
+#define STRETCH_1_2 2
+#define STRETCH_1_4 3
+#define STRETCH_1_N 4
+#define STRETCH_N_1 5
+#define STRETCH_4_1 6
+#define STRETCH_2_1 7
+
+void __stdcall StretchDIB(
+ LPBITMAPINFOHEADER biDst, // --> BITMAPINFO of destination
+ LPVOID lpvDst, // --> to destination bits
+ int DstX, // Destination origin - x coordinate
+ int DstY, // Destination origin - y coordinate
+ int DstXE, // x extent of the BLT
+ int DstYE, // y extent of the BLT
+ LPBITMAPINFOHEADER biSrc, // --> BITMAPINFO of source
+ LPVOID lpvSrc, // --> to source bits
+ int SrcX, // Source origin - x coordinate
+ int SrcY, // Source origin - y coordinate
+ int SrcXE, // x extent of the BLT
+ int SrcYE // y extent of the BLT
+ );
+
+/*
+* an X_FUNC is a function that copies one scanline, stretching or shrinking it
+* to fit a destination scanline. Pick an X_FUNC depending on
+* bitdepth and stretch ratio (1:1, 1:2, 1:4, 1:N, N:1, 4:1, 2:1)
+*
+* the x_fract argument is the delta fraction: it is a representation
+* of the smaller extent (whichever that is) as a fraction of the larger,
+* and is used when stretching or shrinking to advance the pointer to the
+* smaller scanline every (fract) pixels of the larger.
+* Thus if we are expanding 1:8, x_fract will be 1/8, we will advance the
+* source pointer once every 8 pixels, and thus copy each source pixel to
+* 8 dest pixels. Note that if shrinking 8:1, x_fract will still be 1/8
+* and we will use it to control advancement of the dest pointer.
+* the fraction is multiplied by 65536.
+*/
+typedef void (*X_FUNC) (LPBYTE lpSrc,
+ LPBYTE lpDst,
+ int SrcXE,
+ int DstXE,
+ int x_fract);
+
+
+void X_Stretch_1_1_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
+void X_Stretch_1_2_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
+void X_Stretch_1_4_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
+void X_Stretch_1_N_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
+void X_Stretch_N_1_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
+
+void X_Stretch_1_1_16Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
+void X_Stretch_1_2_16Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
+void X_Stretch_1_N_16Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
+void X_Stretch_N_1_16Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
+
+void X_Stretch_1_1_24Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
+void X_Stretch_1_N_24Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
+void X_Stretch_N_1_24Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
+
+void X_Stretch_1_1_32Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
+void X_Stretch_1_N_32Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
+void X_Stretch_N_1_32Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
+
+
+/*
+* Y_Stretch_* functions copy DstYE scanlines (using
+* an X_FUNC to copy each scanline) omitting or duplicating scanlines to
+* fit the destination extent. Pick a Y_ depending on the ratio
+* (1:N, N:1...)
+*/
+
+void Y_Stretch_1_N(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE,int SrcYE, int DstXE,
+ int DstYE, int SrcWidth, int DstWidth, int x_fract,
+ X_FUNC x_func, int nBits);
+
+void Y_Stretch_N_1(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE,int SrcYE, int DstXE,
+ int DstYE, int SrcWidth, int DstWidth, int x_fract,
+ X_FUNC x_func);
+
+/*
+* special case y-stretch functions for 1:2 in both dimensions for 8 and 16 bits
+* takes no X_FUNC arg. Will do entire stretch.
+*/
+void Stretch_1_2_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE,int SrcYE, int DstXE,
+ int DstYE, int SrcWidth, int DstWidth, int x_fract);
+
+
+void Stretch_1_2_16Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE,int SrcYE, int DstXE,
+ int DstYE, int SrcWidth, int DstWidth, int x_fract);
+
+/* straight copy of one scanline of count bytes */
+void X_CopyScanline(LPBYTE lpSrc, LPBYTE lpDst, int count);
+
+
+//
+// Resize function
+//
+void ResizeRGB( BITMAPINFOHEADER *pbiIn, //Src's BitMapInFoHeader
+ const unsigned char * dibBits, //Src bits
+ BITMAPINFOHEADER *pbiOut,
+ unsigned char *pFrame, //Dst bits
+ int iNewWidth, //new W in pixel
+ int iNewHeight) //new H in pixel
+{
+ StretchDIB( pbiOut, // --> BITMAPINFO of destination
+ pFrame, // --> to destination bits
+ 0, // Destination origin - x coordinate
+ 0, // Destination origin - y coordinate
+ iNewWidth, // x extent of the BLT
+ iNewHeight, // y extent of the BLT
+ pbiIn, // --> BITMAPINFO of destination
+ (void*) dibBits, // --> to source bits
+ 0, // Source origin - x coordinate
+ 0, // Source origin - y coordinate
+ pbiIn->biWidth, // x extent of the BLT
+ pbiIn->biHeight // y extent of the BLT
+ );
+
+ return;
+}
+
+
+/* -------------------------------------------------------------------- */
+
+/*
+* StretchFactor
+*
+* calculate the stretch factor (proportion of source extent to destination
+* extent: 1:1, 1:2, 1:4, 1:N, N:1, 4:1,or 2:1) and also the
+* delta fraction (see above comment on X_FUNC). This is the ratio of
+* the smaller extent to the larger extent, represented as a fraction
+* multiplied by 65536.
+*
+* returns: the stretch factor (stores the delta fraction in *pfract)
+*/
+
+int
+StretchFactor(int SrcE, int DstE, int *pfract)
+{
+
+
+ if (SrcE == DstE) {
+ if (pfract != NULL) {
+ pfract = 0;
+ }
+
+ return(STRETCH_1_1);
+
+ }
+
+
+ if (SrcE > DstE) {
+ if (pfract != NULL) {
+ *pfract = ( (DstE << 16) / SrcE) & 0xffff;
+ }
+
+ if (SrcE == (DstE * 2)) {
+ return(STRETCH_2_1);
+ } else if (SrcE == (DstE * 4)) {
+ return(STRETCH_4_1);
+ } else {
+ return(STRETCH_N_1);
+ }
+
+ } else {
+
+ /* calculate delta fraction based on smallest / largest */
+ if (pfract != NULL) {
+ *pfract = ( (SrcE << 16) / DstE) & 0xffff;
+ }
+
+ if (DstE == (SrcE * 2)) {
+ return(STRETCH_1_2);
+ } else if (DstE == (SrcE * 4)) {
+ return(STRETCH_1_4);
+ } else {
+ return(STRETCH_1_N);
+ }
+ }
+}
+
+
+/* -------------------------------------------------------------------- */
+
+/*
+* StretchDIB
+*
+*/
+
+void FAR PASCAL
+StretchDIB(
+ LPBITMAPINFOHEADER biDst, // --> BITMAPINFO of destination
+ LPVOID lpvDst, // --> to destination bits
+ int DstX, // Destination origin - x coordinate
+ int DstY, // Destination origin - y coordinate
+ int DstXE, // x extent of the BLT
+ int DstYE, // y extent of the BLT
+ LPBITMAPINFOHEADER biSrc, // --> BITMAPINFO of source
+ LPVOID lpvSrc, // --> to source bits
+ int SrcX, // Source origin - x coordinate
+ int SrcY, // Source origin - y coordinate
+ int SrcXE, // x extent of the BLT
+ int SrcYE // y extent of the BLT
+ )
+{
+
+ int nBits;
+ int SrcWidth, DstWidth;
+ LPBYTE lpDst = (LPBYTE)lpvDst, lpSrc = (LPBYTE)lpvSrc;
+ int x_fract;
+ int x_factor;
+ int y_factor;
+ X_FUNC xfunc;
+
+
+ /*
+ * chek that sizes are not same
+ */
+ /*if(DstXE == SrcXE && DstYE == SrcYE)
+ {
+ return;
+ }*/
+ /*
+ * check that bit depths are same and 8, 16 or 24
+ */
+
+ if ((nBits = biDst->biBitCount) != biSrc->biBitCount) {
+ return;
+ }
+
+ if ( (nBits != 8 ) && (nBits != 16) && (nBits != 24) &&
+ (nBits != 32)) {
+ return;
+ }
+
+ /*
+ * check that extents are not bad
+ */
+ if ( (SrcXE <= 0) || (SrcYE <= 0) || (DstXE <= 0) || (DstYE <= 0)) {
+ return;
+ }
+
+ /*
+ * calculate width of one scan line in bytes, rounded up to
+ * DWORD boundary.
+ */
+ SrcWidth = (((biSrc->biWidth * nBits) + 31) & ~31) / 8;
+ DstWidth = (((biDst->biWidth * nBits) + 31) & ~31) / 8;
+
+ /*
+ * set initial source and dest pointers
+ */
+ lpSrc += (SrcY * SrcWidth) + ((SrcX * nBits) / 8);
+ lpDst += (DstY * DstWidth) + ((DstX * nBits) / 8);
+
+
+ /*
+ * calculate stretch proportions (1:1, 1:2, 1:N, N:1 etc) and
+ * also the fractional stretch factor. (we are not interested in
+ * the y stretch fraction - this is only used in x stretching.
+ */
+
+ y_factor = StretchFactor(SrcYE, DstYE, NULL);
+ x_factor = StretchFactor(SrcXE, DstXE, &x_fract);
+
+ /*
+ * we have special case routines for 1:2 in both dimensions
+ * for 8 and 16 bits
+ */
+ if ((y_factor == x_factor) && (y_factor == STRETCH_1_2)) {
+
+ if (nBits == 8) {
+ //StartCounting();
+ Stretch_1_2_8Bits(lpSrc, lpDst, SrcXE, SrcYE,
+ DstXE, DstYE, SrcWidth, DstWidth,
+ x_fract);
+ //EndCounting("8 bit");
+ return;
+
+ } else if (nBits == 16) {
+ //StartCounting();
+ Stretch_1_2_16Bits(lpSrc, lpDst, SrcXE, SrcYE,
+ DstXE, DstYE, SrcWidth, DstWidth,
+ x_fract);
+ //EndCounting("16 bit");
+ return;
+ }
+ }
+
+
+ /* pick an X stretch function */
+ switch(nBits) {
+
+ case 8:
+ switch(x_factor) {
+ case STRETCH_1_1:
+ xfunc = X_Stretch_1_1_8Bits;
+ break;
+
+ case STRETCH_1_2:
+ xfunc = X_Stretch_1_2_8Bits;
+ break;
+
+ case STRETCH_1_4:
+ xfunc = X_Stretch_1_4_8Bits;
+ break;
+
+ case STRETCH_1_N:
+ xfunc = X_Stretch_1_N_8Bits;
+ break;
+
+ case STRETCH_N_1:
+ case STRETCH_4_1:
+ case STRETCH_2_1:
+ xfunc = X_Stretch_N_1_8Bits;
+ break;
+
+ }
+ break;
+
+ case 16:
+ switch(x_factor) {
+ case STRETCH_1_1:
+ xfunc = X_Stretch_1_1_16Bits;
+ break;
+
+ case STRETCH_1_2:
+ xfunc = X_Stretch_1_2_16Bits;
+ break;
+
+ case STRETCH_1_4:
+ case STRETCH_1_N:
+ xfunc = X_Stretch_1_N_16Bits;
+ break;
+
+ case STRETCH_N_1:
+ case STRETCH_4_1:
+ case STRETCH_2_1:
+ xfunc = X_Stretch_N_1_16Bits;
+ break;
+
+ }
+ break;
+
+ case 24:
+ switch(x_factor) {
+ case STRETCH_1_1:
+ xfunc = X_Stretch_1_1_24Bits;
+ break;
+
+ case STRETCH_1_2:
+ case STRETCH_1_4:
+ case STRETCH_1_N:
+ xfunc = X_Stretch_1_N_24Bits;
+ break;
+
+ case STRETCH_N_1:
+ case STRETCH_4_1:
+ case STRETCH_2_1:
+ xfunc = X_Stretch_N_1_24Bits;
+ break;
+
+ }
+ break;
+
+ case 32:
+ switch(x_factor) {
+ case STRETCH_1_1:
+ xfunc = X_Stretch_1_1_32Bits;
+ break;
+
+ case STRETCH_1_2:
+ case STRETCH_1_4:
+ case STRETCH_1_N:
+ xfunc = X_Stretch_1_N_32Bits;
+ break;
+
+ case STRETCH_N_1:
+ case STRETCH_4_1:
+ case STRETCH_2_1:
+ xfunc = X_Stretch_N_1_32Bits;
+ break;
+
+ }
+ break;
+
+ }
+
+
+ /*
+ * now call appropriate stretching function depending
+ * on the y stretch factor
+ */
+ switch (y_factor) {
+ case STRETCH_1_1:
+ case STRETCH_1_2:
+ case STRETCH_1_4:
+ case STRETCH_1_N:
+ Y_Stretch_1_N(lpSrc, lpDst, SrcXE, SrcYE,
+ DstXE, DstYE, SrcWidth, DstWidth, x_fract, xfunc, nBits);
+ break;
+
+ case STRETCH_N_1:
+ case STRETCH_4_1:
+ case STRETCH_2_1:
+ Y_Stretch_N_1(lpSrc, lpDst, SrcXE, SrcYE,
+ DstXE, DstYE, SrcWidth, DstWidth, x_fract, xfunc);
+ break;
+
+ }
+ return;
+}
+
+
+/* ---- y stretching -------------------------------------------- */
+
+/*
+* call an X_FUNC to copy scanlines from lpSrc to lpDst. Duplicate or
+* omit scanlines to stretch SrcYE to DstYE.
+*/
+
+
+/*
+* Y_Stretch_1_N
+*
+* write DstYE scanlines based on SrcYE scanlines, DstYE > SrcYE
+*
+*/
+
+void
+Y_Stretch_1_N(LPBYTE lpSrc,
+ LPBYTE lpDst,
+ int SrcXE,
+ int SrcYE,
+ int DstXE,
+ int DstYE,
+ int SrcWidth,
+ int DstWidth,
+ int x_fract,
+ X_FUNC x_func,
+ int nBits)
+{
+
+ int ydelta;
+ register int i;
+ LPBYTE lpPrev = NULL;
+
+ ydelta = DstYE -1;
+
+ for (i = 0; i < DstYE; i++) {
+
+ /* have we already stretched this scanline ? */
+ if (lpPrev == NULL) {
+ /* no - copy one scanline */
+ (*x_func)(lpSrc, lpDst, SrcXE, DstXE, x_fract);
+ lpPrev = lpDst;
+ } else {
+ /* yes - this is a duplicate scanline. do
+ * a straight copy of one that has already
+ * been stretched/shrunk
+ */
+ X_CopyScanline(lpPrev, lpDst, DstXE * nBits / 8);
+ }
+
+ /* advance dest pointer */
+ lpDst += DstWidth;
+
+ /* should we advance source pointer this time ? */
+ if ( (ydelta -= SrcYE) < 0) {
+ ydelta += DstYE;
+ lpSrc += SrcWidth;
+ lpPrev = NULL;
+ }
+ }
+}
+
+
+/*
+* Y_Stretch_N_1
+*
+* write DstYE scanlines based on SrcYE scanlines, DstYE < SrcYE
+*
+*/
+void
+Y_Stretch_N_1(LPBYTE lpSrc,
+ LPBYTE lpDst,
+ int SrcXE,
+ int SrcYE,
+ int DstXE,
+ int DstYE,
+ int SrcWidth,
+ int DstWidth,
+ int x_fract,
+ X_FUNC x_func)
+{
+
+ int ydelta;
+ register int i;
+
+ ydelta = SrcYE -1;
+
+ for (i = 0; i < DstYE; i++) {
+
+ /* copy one scanline */
+ (*x_func)(lpSrc, lpDst, SrcXE, DstXE, x_fract);
+
+ /* advance dest pointer */
+ lpDst += DstWidth;
+
+ /* how many times do we advance source pointer this time ? */
+ do {
+ lpSrc += SrcWidth;
+ ydelta -= DstYE;
+ } while (ydelta >= 0);
+
+ ydelta += SrcYE;
+ }
+}
+
+/* ---8-bit X stretching -------------------------------------------------- */
+
+/*
+* X_Stretch_1_N_8Bits
+*
+* copy one scan line, stretching 1:N (DstXE > SrcXE). For 8-bit depth.
+*/
+void
+X_Stretch_1_N_8Bits(LPBYTE lpSrc,
+ LPBYTE lpDst,
+ int SrcXE,
+ int DstXE,
+ int x_fract)
+{
+ int xdelta;
+ register int i;
+
+ xdelta = DstXE -1;
+
+ for (i = 0; i < DstXE; i++) {
+
+ /* copy one byte and advance dest */
+ *lpDst++ = *lpSrc;
+
+ /* should we advance source pointer this time ? */
+ if ( (xdelta -= SrcXE) < 0) {
+ xdelta += DstXE;
+ lpSrc++;
+ }
+ }
+}
+
+
+/*
+* X_Stretch_N_1_8Bits
+*
+* copy one scan line, shrinking N:1 (DstXE < SrcXE). For 8-bit depth.
+*/
+void
+X_Stretch_N_1_8Bits(LPBYTE lpSrc,
+ LPBYTE lpDst,
+ int SrcXE,
+ int DstXE,
+ int x_fract)
+{
+ int xdelta;
+ register int i;
+
+ xdelta = SrcXE -1;
+
+ for (i = 0; i < DstXE; i++) {
+
+ /* copy one byte and advance dest */
+ *lpDst++ = *lpSrc;
+
+ /* how many times do we advance source pointer this time ? */
+ do {
+ lpSrc++;
+ xdelta -= DstXE;
+ } while (xdelta >= 0);
+
+ xdelta += SrcXE;
+ }
+}
+
+/*
+* copy one scanline of count bytes from lpSrc to lpDst. used by 1:1
+* scanline functions for all bit depths
+*/
+void
+X_CopyScanline(LPBYTE lpSrc, LPBYTE lpDst, int count)
+{
+ register int i;
+
+ /*
+ * if the alignment of lpSrc and lpDst is the same, then
+ * we can get them aligned and do a faster copy
+ */
+ if (((DWORD_PTR) lpSrc & 0x3) == ( (DWORD_PTR) lpDst & 0x3)) {
+
+ /* align on WORD boundary */
+ if ( (DWORD_PTR) lpSrc & 0x1) {
+ *lpDst++ = *lpSrc++;
+ count--;
+ }
+
+ /* align on DWORD boundary */
+ if ((DWORD_PTR) lpSrc & 0x2) {
+ * ((LPWORD) lpDst) = *((LPWORD) lpSrc);
+ lpDst += sizeof(WORD);
+ lpSrc += sizeof(WORD);
+ count -= sizeof(WORD);
+ }
+
+ /* copy whole DWORDS */
+ for ( i = (count / 4); i > 0; i--) {
+ *((LPDWORD) lpDst) = *((LPDWORD) lpSrc);
+ lpSrc += sizeof(DWORD);
+ lpDst += sizeof(DWORD);
+ }
+ } else {
+ /* the lpSrc and lpDst pointers are different
+ * alignment, so leave them unaligned and
+ * copy all the whole DWORDs
+ */
+ for (i = (count / 4); i> 0; i--) {
+ *( (DWORD UNALIGNED FAR *) lpDst) =
+ *((DWORD UNALIGNED FAR *) lpSrc);
+ lpSrc += sizeof(DWORD);
+ lpDst += sizeof(DWORD);
+ }
+ }
+
+ /* in either case, copy last (up to 3) bytes. */
+ for ( i = count % 4; i > 0; i--) {
+ *lpDst++ = *lpSrc++;
+ }
+}
+
+/*
+* X_Stretch_1_1_8Bits
+*
+* copy a scanline with no change (1:1)
+*/
+void
+X_Stretch_1_1_8Bits(LPBYTE lpSrc,
+ LPBYTE lpDst,
+ int SrcXE,
+ int DstXE,
+ int x_fract)
+{
+
+ X_CopyScanline(lpSrc, lpDst, DstXE);
+}
+
+
+/*
+* X_Stretch_1_2_8Bits
+*
+* copy a scanline, doubling all the pixels (1:2)
+*/
+void
+X_Stretch_1_2_8Bits(LPBYTE lpSrc,
+ LPBYTE lpDst,
+ int SrcXE,
+ int DstXE,
+ int x_fract)
+{
+ WORD wPix;
+ register int i;
+
+ for (i = 0; i < SrcXE; i++) {
+
+ /* get a pixel and double it */
+ wPix = *lpSrc++;
+ wPix |= (wPix << 8);
+ * ((WORD UNALIGNED *) lpDst) = wPix;
+ lpDst += sizeof(WORD);
+ }
+}
+
+
+/*
+* X_Stretch_1_4_8Bits
+*
+* copy a scanline, quadrupling all the pixels (1:4)
+*/
+void
+X_Stretch_1_4_8Bits(LPBYTE lpSrc,
+ LPBYTE lpDst,
+ int SrcXE,
+ int DstXE,
+ int x_fract)
+{
+ DWORD dwPix;
+ register int i;
+
+ for (i = 0; i < SrcXE; i++) {
+
+ /* get a pixel and make four copies of it */
+ dwPix = *lpSrc++;
+ dwPix |= (dwPix <<8);
+ dwPix |= (dwPix << 16);
+ * ((DWORD UNALIGNED *) lpDst) = dwPix;
+ lpDst += sizeof(DWORD);
+ }
+}
+
+
+/* -- 16-bit X functions -----------------------------------------------*/
+
+/*
+* copy one scan-line of 16 bits with no change (1:1)
+*/
+void
+X_Stretch_1_1_16Bits(LPBYTE lpSrc,
+ LPBYTE lpDst,
+ int SrcXE,
+ int DstXE,
+ int x_fract)
+{
+
+ X_CopyScanline(lpSrc, lpDst, DstXE * sizeof(WORD));
+
+}
+
+
+/*
+* copy one scanline of 16 bpp duplicating each pixel
+*/
+void
+X_Stretch_1_2_16Bits(LPBYTE lpSrc,
+ LPBYTE lpDst,
+ int SrcXE,
+ int DstXE,
+ int x_fract)
+{
+
+ DWORD dwPix;
+ register int i;
+
+ for (i = 0; i < SrcXE; i++) {
+
+ /* get a pixel and double it */
+ dwPix = * ((WORD *)lpSrc);
+ dwPix |= (dwPix << 16);
+ * ((DWORD UNALIGNED *) lpDst) = dwPix;
+
+ lpDst += sizeof(DWORD);
+ lpSrc += sizeof(WORD);
+ }
+
+}
+
+/*
+* copy one scanline of 16 bits, stretching 1:n (dest > source)
+*/
+void
+X_Stretch_1_N_16Bits(LPBYTE lpSrc,
+ LPBYTE lpDst,
+ int SrcXE,
+ int DstXE,
+ int x_fract)
+{
+ int xdelta;
+ register int i;
+
+ xdelta = DstXE -1;
+
+ for (i = 0; i < DstXE; i++) {
+
+ /* copy one pixel and advance dest */
+ *((WORD *) lpDst) = *((WORD *) lpSrc);
+
+ lpDst += sizeof(WORD);
+
+ /* should we advance source pointer this time ? */
+ if ( (xdelta -= SrcXE) < 0) {
+ xdelta += DstXE;
+ lpSrc += sizeof(WORD);
+ }
+ }
+}
+
+/*
+* copy one scanline of 16bits, shrinking n:1 (dest < source)
+*/
+void
+X_Stretch_N_1_16Bits(LPBYTE lpSrc,
+ LPBYTE lpDst,
+ int SrcXE,
+ int DstXE,
+ int x_fract)
+{
+
+ int xdelta;
+ register int i;
+
+ xdelta = SrcXE -1;
+
+ for (i = 0; i < DstXE; i++) {
+
+ /* copy one pixel and advance dest */
+ *((WORD *) lpDst) = *((WORD *)lpSrc);
+
+ lpDst += sizeof(WORD);
+
+ /* how many times do we advance source pointer this time ? */
+ do {
+ lpSrc += sizeof(WORD);
+ xdelta -= DstXE;
+ } while (xdelta >= 0);
+
+ xdelta += SrcXE;
+ }
+
+}
+
+
+/* 24-bits ---------------------------------------------------------*/
+
+/*
+* copy one 24-bpp scanline as is (1:1)
+*/
+void
+X_Stretch_1_1_24Bits(LPBYTE lpSrc,
+ LPBYTE lpDst,
+ int SrcXE,
+ int DstXE,
+ int x_fract)
+{
+ X_CopyScanline(lpSrc, lpDst, DstXE * 3);
+}
+
+/*
+* copy one 24-bpp scanline stretching 1:n (dest > source)
+*/
+void
+X_Stretch_1_N_24Bits(LPBYTE lpSrc,
+ LPBYTE lpDst,
+ int SrcXE,
+ int DstXE,
+ int x_fract)
+{
+
+ int xdelta;
+ register int i;
+
+ xdelta = DstXE -1;
+
+ for (i = 0; i < DstXE; i++) {
+ /* copy first word of pixel and advance dest */
+ *((WORD UNALIGNED *) lpDst) = *((WORD UNALIGNED *) lpSrc);
+
+ lpDst += sizeof(WORD);
+
+ /* copy third byte and advance dest */
+ *lpDst++ = lpSrc[sizeof(WORD)];
+
+ /* should we advance source pointer this time ? */
+ if ( (xdelta -= SrcXE) < 0) {
+ xdelta += DstXE;
+ lpSrc += 3;
+ }
+ }
+}
+
+/*
+* copy one scanline of 24 bits, shrinking n:1 (dest < source)
+*/
+void
+X_Stretch_N_1_24Bits(LPBYTE lpSrc,
+ LPBYTE lpDst,
+ int SrcXE,
+ int DstXE,
+ int x_fract)
+{
+ int xdelta;
+ register int i;
+
+ xdelta = SrcXE -1;
+
+ for (i = 0; i < DstXE; i++) {
+
+ /* copy first word of pixel and advance dest */
+ *((WORD UNALIGNED *) lpDst) = *((WORD UNALIGNED *) lpSrc);
+
+ lpDst += sizeof(WORD);
+
+ /* copy third byte and advance dest */
+ *lpDst++ = lpSrc[sizeof(WORD)];
+
+
+ /* how many times do we advance source pointer this time ? */
+ do {
+ lpSrc += 3;
+ xdelta -= DstXE;
+ } while (xdelta >= 0);
+
+ xdelta += SrcXE;
+ }
+}
+
+
+/* 32-bits ---------------------------------------------------------*/
+
+/*
+* copy one 32-bpp scanline as is (1:1)
+*/
+void
+X_Stretch_1_1_32Bits(LPBYTE lpSrc,
+ LPBYTE lpDst,
+ int SrcXE,
+ int DstXE,
+ int x_fract)
+{
+ X_CopyScanline((BYTE*) lpSrc, (BYTE*) lpDst, DstXE * sizeof( RGBQUAD ) );
+}
+
+/*
+* copy one 32-bpp scanline stretching 1:n (dest > source)
+*/
+void
+X_Stretch_1_N_32Bits(LPBYTE lpSrc0,
+ LPBYTE lpDst0,
+ int SrcXE,
+ int DstXE,
+ int x_fract)
+{
+
+ int xdelta;
+ register int i;
+
+ RGBQUAD *lpSrc=(RGBQUAD *)lpSrc0;
+ RGBQUAD *lpDst=(RGBQUAD *)lpDst0;
+
+
+ xdelta = DstXE -1;
+
+ for (i = 0; i < DstXE; i++)
+ {
+ /* copy first word of pixel and advance dest */
+ *lpDst = *lpSrc;
+ lpDst++;
+
+ /* should we advance source pointer this time ? */
+ if ( (xdelta -= SrcXE) < 0)
+ {
+ xdelta += DstXE;
+ lpSrc++;
+ }
+ }
+}
+
+/*
+* copy one scanline of 32 bits, shrinking n:1 (dest < source)
+*/
+void
+X_Stretch_N_1_32Bits(LPBYTE lpSrc0,
+ LPBYTE lpDst0,
+ int SrcXE,
+ int DstXE,
+ int x_fract)
+{
+ int xdelta;
+ register int i;
+
+ RGBQUAD *lpSrc=(RGBQUAD *)lpSrc0;
+ RGBQUAD *lpDst=(RGBQUAD *)lpDst0;
+
+ xdelta = SrcXE -1;
+
+ for (i = 0; i < DstXE; i++)
+ {
+ *lpDst = *lpSrc;
+ lpDst++;
+
+ /* how many times do we advance source pointer this time ? */
+ do
+ {
+ lpSrc++;
+ xdelta -= DstXE;
+ } while (xdelta >= 0);
+
+ xdelta += SrcXE;
+ }
+}
+
+
+
+
+/* -- special-case 1:2 -------------------------------------------*/
+
+/*
+* stretch 1:2 in both directions, for 8 bits.
+*
+* An experiment was done on x86 to only write every other line during
+* the stretch and when the whole frame was done to use memcpy to fill
+* in the gaps. This is slower than doing the stretch in a single pass.
+*/
+void
+Stretch_1_2_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE,int SrcYE, int DstXE,
+ int DstYE, int SrcWidth, int DstWidth, int x_fract)
+{
+
+ int SrcInc, DstInc;
+ register int i, j;
+ WORD wPix;
+ DWORD dwPix4;
+
+ /* amount to advance source by at the end of each scan */
+ SrcInc = SrcWidth - SrcXE;
+
+
+ /* amount to advance dest by at the end of each scan - note
+ * that we write two scans at once, so advance past the next
+ * scan line
+ */
+ DstInc = (DstWidth * 2) - DstXE;
+
+ /*
+ * we would like to copy the pixels DWORD at a time. this means
+ * being aligned. if we are currently aligned on a WORD boundary,
+ * then copy one pixel to get aligned. If we are on a byte
+ * boundary, we can never get aligned, so use the slower loop.
+ */
+ if ( ((DWORD_PTR)lpDst) & 1) {
+
+ /*
+ * dest is byte aligned - so we can never align it
+ * by writing WORDs - use slow loop.
+ */
+ for (i = 0; i < SrcYE; i++) {
+
+ for (j = 0; j < SrcXE; j++) {
+
+ /* get a pixel and double it */
+
+ wPix = *lpSrc++;
+ wPix |= (wPix<<8);
+
+
+ /* write doubled pixel to this scanline */
+
+ *( (WORD UNALIGNED *) lpDst) = wPix;
+
+ /* write double pixel to next scanline */
+ *( (WORD UNALIGNED *) (lpDst + DstWidth)) = wPix;
+
+ lpDst += sizeof(WORD);
+ }
+ lpSrc += SrcInc;
+ lpDst += DstInc;
+ }
+ return;
+ }
+
+ /*
+ * this will be the aligned version. align each scan line
+ */
+ for ( i = 0; i < SrcYE; i++) {
+
+ /* count of pixels remaining */
+ j = SrcXE;
+
+ /* align this scan line */
+ if (((DWORD_PTR)lpDst) & 2) {
+
+ /* word aligned - copy one doubled pixel and we are ok */
+ wPix = *lpSrc++;
+ wPix |= (wPix << 8);
+
+ *( (WORD *) lpDst) = wPix;
+ *( (WORD *) (lpDst + DstWidth)) = wPix;
+ lpDst += sizeof(WORD);
+
+ j -= 1;
+ }
+
+
+ /* now dest is aligned - so loop eating two pixels at a time
+ * until there is at most one left
+ */
+ for ( ; j > 1; j -= 2) {
+
+ /* read two pixels and double them */
+ wPix = * ((WORD UNALIGNED *) lpSrc);
+ lpSrc += sizeof(WORD);
+
+ dwPix4 = (wPix & 0xff) | ((wPix & 0xff) << 8);
+ dwPix4 |= ((wPix & 0xff00) << 8) | ((wPix & 0xff00) << 16);
+ *((DWORD *) lpDst) = dwPix4;
+ *((DWORD *) (lpDst + DstWidth)) = dwPix4;
+
+ lpDst += sizeof(DWORD);
+ }
+
+ /* odd byte remaining ? */
+ if (j > 0) {
+ /* word aligned - copy one doubled pixel and we are ok */
+ wPix = *lpSrc++;
+ wPix |= (wPix << 8);
+
+ *( (WORD *) lpDst) = wPix;
+ *( (WORD *) (lpDst + DstWidth)) = wPix;
+ lpDst += sizeof(WORD);
+
+ j -= 1;
+ }
+ lpSrc += SrcInc;
+ lpDst += DstInc;
+ }
+}
+
+
+
+/* ----------------------------------------------------------------*/
+
+/*
+* stretch 1:2 in both directions, for 16-bits
+*/
+
+void
+Stretch_1_2_16Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE,int SrcYE, int DstXE,
+ int DstYE, int SrcWidth, int DstWidth, int x_fract)
+
+{
+ int SrcInc, DstInc;
+ register int i, j;
+ DWORD dwPix;
+
+ /* amount to advance source by at the end of each scan */
+ SrcInc = SrcWidth - (SrcXE * sizeof(WORD));
+
+
+ /* amount to advance dest by at the end of each scan - note
+ * that we write two scans at once, so advance past the next
+ * scan line
+ */
+ DstInc = (DstWidth * 2) - (DstXE * sizeof(WORD));
+
+ for (i = 0; i < SrcYE; i++) {
+
+ for (j = 0; j < SrcXE; j++) {
+
+ /* get a pixel and double it */
+
+ dwPix = *((WORD *)lpSrc);
+ dwPix |= (dwPix<<16);
+
+ lpSrc += sizeof(WORD);
+
+ /* write doubled pixel to this scanline */
+
+ *( (DWORD UNALIGNED *) lpDst) = dwPix;
+
+ /* write double pixel to next scanline */
+ *( (DWORD UNALIGNED *) (lpDst + DstWidth)) = dwPix;
+
+ lpDst += sizeof(DWORD);
+ }
+ lpSrc += SrcInc;
+ lpDst += DstInc;
+
+ }
+}
diff --git a/plugins/pluginDirectShow/internals/Resizer.h b/plugins/pluginDirectShow/internals/Resizer.h
new file mode 100644
index 0000000..6c76970
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/Resizer.h
@@ -0,0 +1,76 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+/*
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ */
+#ifndef PLUGIN_DSHOW_RESIZER_H
+#define PLUGIN_DSHOW_RESIZER_H
+
+#include "plugin_dshow_config.h"
+
+/*
+* StretchC.C
+*
+* StretchBlt for DIBs
+*
+* C version of stretch.asm: StretchDIB optimised for AVI.
+*
+* NOTES
+* - does not handle mirroring in x or y
+* - does not handle pixel translation
+* - will not work in place.
+*/
+
+
+/* Outline:
+*
+* we select a y-stretching function depending on the ratio (eg 1:N or N:1).
+* it copies scanlines from source to destination, duplicating or omitting
+* scanlines as necessary to fit the destination. It copies each scanline
+* via the X_FUNC function we passed as an argument: this copies one scanline
+* duplicating or omitting pixels to fit the destination: we select an X_FUNC
+* depending on the bit-depth as well as the x-stretching ratio.
+*
+* both x and y stretching functions use the following basic model for deciding
+* when to insert/omit elements:
+*
+* delta = <larger extent> -1;
+*
+* for (number of destination elements) {
+*
+* copy one element
+* advance pointer to larger region
+* delta -= <smaller extent>
+* if (delta < 0) {
+* delta += <larger extent>;
+* advance pointer to smaller region
+* }
+* }
+*/
+
+#include <streams.h>
+
+
+void ResizeRGB( BITMAPINFOHEADER *pbiIn, //Src's BitMapInFoHeader
+ const unsigned char * dibBits, //Src bits
+ BITMAPINFOHEADER *pbiOut,
+ unsigned char *pFrame, //Dst bits
+ int iNewWidth, //new W in pixel
+ int iNewHeight); //new H in pixel
+
+#endif //RESIZER_H
diff --git a/plugins/pluginDirectShow/internals/VideoDisplayName.cxx b/plugins/pluginDirectShow/internals/VideoDisplayName.cxx
new file mode 100644
index 0000000..6b4d0b0
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/VideoDisplayName.cxx
@@ -0,0 +1,37 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#include "internals/VideoDisplayName.h"
+
+VideoDisplayName::VideoDisplayName(std::string name_, std::string descr) : name(name_), description(descr)
+{
+}
+
+std::string VideoDisplayName::getName() const
+{
+ return this->name;
+}
+
+std::string VideoDisplayName::getDescription() const
+{
+ return this->description;
+}
+
+int VideoDisplayName::operator==(const VideoDisplayName &dev) const
+{
+ return this->name == dev.name;
+}
diff --git a/plugins/pluginDirectShow/internals/VideoDisplayName.h b/plugins/pluginDirectShow/internals/VideoDisplayName.h
new file mode 100644
index 0000000..82dc0d0
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/VideoDisplayName.h
@@ -0,0 +1,43 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#ifndef PLUGIN_DSHOW_VIDEODISPLAYNAME_H
+#define PLUGIN_DSHOW_VIDEODISPLAYNAME_H
+
+#include "plugin_dshow_config.h"
+
+#include <string>
+
+class VideoDisplayName
+{
+public:
+ VideoDisplayName() {}
+
+ VideoDisplayName(std::string name, std::string description);
+
+ std::string getName() const;
+
+ std::string getDescription() const;
+
+ int operator==( const VideoDisplayName &dev ) const;
+
+private:
+ std::string name;
+ std::string description;
+};
+
+#endif /* PLUGIN_DSHOW_VIDEODISPLAYNAME_H */
diff --git a/plugins/pluginDirectShow/internals/VideoFrame.h b/plugins/pluginDirectShow/internals/VideoFrame.h
new file mode 100644
index 0000000..2c910a6
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/VideoFrame.h
@@ -0,0 +1,107 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#ifndef PLUGIN_DSHOW_VIDEOFRAME_H
+#define PLUGIN_DSHOW_VIDEOFRAME_H
+
+// Define supported video formats
+typedef enum _VIDEOFORMAT
+{
+ VIDEOFORMAT_NULL = 0, // 0 x 0 : Null
+ VIDEOFORMAT_SQCIF, // 128 x 96 : SQCIF
+ VIDEOFORMAT_QCIF, // 176 x 144 : QCIF
+ VIDEOFORMAT_QVGA, // 320 x 240 : QVGA
+ VIDEOFORMAT_CIF, // 352 x 288 : CIF
+ VIDEOFORMAT_IOS_MEDIUM, // 480 x 360 : IOS_MEDIUM
+ VIDEOFORMAT_VGA, // 640 x 480 : VGA
+ VIDEOFORMAT_4CIF, // 704 x 576 : 4CIF
+ VIDEOFORMAT_SVGA, // 800 x 600 : SVGA
+ VIDEOFORMAT_XGA, // 1024 x 768 : XGA
+ VIDEOFORMAT_SXGA, // 1280 x 1024 : SXGA
+ VIDEOFORMAT_16CIF, // 1408 x 1152 : 16CIF
+} VIDEOFORMAT;
+
+
+// Macro to convert a video format to its size
+#define VIDEOFORMAT_TO_SIZE(format, width, height) \
+ switch(format) \
+ { \
+ case VIDEOFORMAT_SQCIF: width = 128; height = 96; break; \
+ case VIDEOFORMAT_QCIF: width = 176; height = 144; break; \
+ case VIDEOFORMAT_QVGA: width = 320; height = 240; break; \
+ case VIDEOFORMAT_CIF: width = 352; height = 288; break; \
+ case VIDEOFORMAT_IOS_MEDIUM: width = 480; height = 360; break; \
+ case VIDEOFORMAT_VGA: width = 640; height = 480; break; \
+ case VIDEOFORMAT_4CIF: width = 704; height = 576; break; \
+ case VIDEOFORMAT_SVGA: width = 800; height = 600; break; \
+ case VIDEOFORMAT_XGA: width = 1024; height = 768; break; \
+ case VIDEOFORMAT_SXGA: width = 1280; height = 1024; break; \
+ case VIDEOFORMAT_16CIF: width = 1408; height = 1152; break; \
+ case VIDEOFORMAT_NULL: \
+ default: width = 0; height = 0; break; \
+ } \
+
+
+// Macro to get a video format from its size
+#define SIZE_TO_VIDEOFORMAT(width, height, format) \
+ if ((width == 128) && (height = 96)) format = VIDEOFORMAT_SQCIF; \
+ else if ((width == 176) && (height = 144)) format = VIDEOFORMAT_QCIF; \
+ else if ((width == 320) && (height = 240)) format = VIDEOFORMAT_QVGA; \
+ else if ((width == 352) && (height = 288)) format = VIDEOFORMAT_CIF; \
+ else if ((width == 480) && (height = 360)) format = VIDEOFORMAT_IOS_MEDIUM; \
+ else if ((width == 640) && (height = 480)) format = VIDEOFORMAT_VGA; \
+ else if ((width == 704) && (height = 576)) format = VIDEOFORMAT_4CIF; \
+ else if ((width == 800) && (height = 600)) format = VIDEOFORMAT_SVGA; \
+ else if ((width == 1024) && (height = 768)) format = VIDEOFORMAT_XGA; \
+ else if ((width == 1280) && (height = 1024)) format = VIDEOFORMAT_SXGA; \
+ else if ((width == 1408) && (height = 1152)) format = VIDEOFORMAT_16CIF; \
+ else format = VIDEOFORMAT_NULL; \
+
+
+// Constants for consumer and producer Ids
+#define GRABBER_VIDEO_ID 0x1FFFFFFF
+#define REMOTE_VIDEO_ID 0x2FFFFFFF
+
+
+class VideoFrame
+{
+public:
+ VideoFrame() { this->data = NULL; };
+ virtual ~VideoFrame() { if(this->data) { this->data = NULL;} };
+
+ int getWidth() { return this->width; };
+ int getHeight() { return this->height; };
+ int getBitsPerPixel() { return this->bpp; };
+ int getTotalBits () { return this->width * this->height * (this->bpp/8); };
+ void* getData() { return this->data; };
+
+ void setWidth(int width_) { this->width = width_; };
+ void setHeight(int height_) { this->height = height_; };
+ void setBitsPerPixel( int bpp_) { this->bpp = bpp_; };
+ void setData( void* data_) { this->data = data_; };
+
+ VIDEOFORMAT getSize();
+ void setSize(VIDEOFORMAT format);
+
+private:
+ void *data;
+ int width;
+ int height;
+ int bpp;
+};
+
+#endif /* VIDEOFRAME_H */
diff --git a/plugins/pluginDirectShow/internals/VideoGrabberName.cxx b/plugins/pluginDirectShow/internals/VideoGrabberName.cxx
new file mode 100644
index 0000000..4b418cf
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/VideoGrabberName.cxx
@@ -0,0 +1,37 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#include "internals/VideoGrabberName.h"
+
+VideoGrabberName::VideoGrabberName(std::string name_, std::string descr) : name(name_), description(descr)
+{
+}
+
+std::string VideoGrabberName::getName() const
+{
+ return this->name;
+}
+
+std::string VideoGrabberName::getDescription() const
+{
+ return this->description;
+}
+
+int VideoGrabberName::operator==(const VideoGrabberName &dev) const
+{
+ return this->name == dev.name;
+} \ No newline at end of file
diff --git a/plugins/pluginDirectShow/internals/VideoGrabberName.h b/plugins/pluginDirectShow/internals/VideoGrabberName.h
new file mode 100644
index 0000000..0bb45b5
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/VideoGrabberName.h
@@ -0,0 +1,43 @@
+/* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#ifndef PLUGIN_DSHOW_VIDEOGRABBERNAME_H
+#define PLUGIN_DSHOW_VIDEOGRABBERNAME_H
+
+#include "plugin_dshow_config.h"
+
+#include<string>
+
+class VideoGrabberName
+{
+public:
+ VideoGrabberName() {}
+
+ VideoGrabberName(std::string name, std::string description);
+
+ std::string getName() const;
+
+ std::string getDescription() const;
+
+ int operator==( const VideoGrabberName &dev ) const;
+
+private:
+ std::string name;
+ std::string description;
+};
+
+#endif /* PLUGIN_DSHOW_VIDEOGRABBERNAME_H */
diff --git a/plugins/pluginDirectShow/internals/wince/CPropertyBag.cxx b/plugins/pluginDirectShow/internals/wince/CPropertyBag.cxx
new file mode 100644
index 0000000..a6b436a
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/wince/CPropertyBag.cxx
@@ -0,0 +1,108 @@
+#if defined(_WIN32_WCE)
+//
+// Copyright (c) Microsoft Corporation.  All rights reserved.
+//
+//
+// Use of this source code is subject to the terms of the Microsoft end-user
+// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
+// If you did not accept the terms of the EULA, you are not authorized to use
+// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
+// install media.
+//
+#include <windows.h>
+#include <Ocidl.h>
+#include <oleauto.h>
+
+#include "internals/wince/CPropertyBag.h"
+
+CPropertyBag::CPropertyBag() : _refCount(1), pVar(0)
+{
+}
+
+CPropertyBag::~CPropertyBag()
+{
+ VAR_LIST *pTemp = pVar;
+ HRESULT hr = S_OK;
+
+ while(pTemp) {
+ VAR_LIST *pDel = pTemp;
+ VariantClear(&pTemp->var);
+ SysFreeString(pTemp->pBSTRName);
+ pTemp = pTemp->pNext;
+ delete pDel;
+ }
+
+}
+
+HRESULT STDMETHODCALLTYPE
+CPropertyBag::Read(LPCOLESTR pszPropName,
+ VARIANT *_pVar,
+ IErrorLog *pErrorLog)
+{
+ VAR_LIST *pTemp = pVar;
+ HRESULT hr = S_OK;
+
+ while (pTemp) {
+ if (0 == wcscmp(pszPropName, pTemp->pBSTRName)) {
+ hr = VariantCopy(_pVar, &pTemp->var);
+ break;
+ }
+ pTemp = pTemp->pNext;
+ }
+ return hr;
+}
+
+
+HRESULT STDMETHODCALLTYPE
+CPropertyBag::Write(LPCOLESTR pszPropName,
+ VARIANT *_pVar)
+{
+ HRESULT hr = S_OK;
+ VAR_LIST *pTemp = new VAR_LIST();
+ ASSERT(pTemp);
+
+ if ( !pTemp ) {
+ return E_OUTOFMEMORY;
+ }
+
+ VariantInit(&pTemp->var);
+ pTemp->pBSTRName = SysAllocString(pszPropName);
+ pTemp->pNext = pVar;
+ pVar = pTemp;
+ return VariantCopy(&pTemp->var, _pVar);
+}
+
+ULONG STDMETHODCALLTYPE
+CPropertyBag::AddRef()
+{
+ return InterlockedIncrement((LONG *)&_refCount);
+}
+
+ULONG STDMETHODCALLTYPE
+CPropertyBag::Release()
+{
+ ASSERT(_refCount != 0xFFFFFFFF);
+ ULONG ret = InterlockedDecrement((LONG *)&_refCount);
+ if (!ret) {
+ delete this;
+ }
+ return ret;
+}
+
+HRESULT STDMETHODCALLTYPE
+CPropertyBag::QueryInterface(REFIID riid, void** ppv)
+{
+ if (!ppv) {
+ return E_POINTER;
+ }
+ if (riid == IID_IPropertyBag) {
+ *ppv = static_cast<IPropertyBag*>(this);
+ }
+ else {
+ return *ppv = 0, E_NOINTERFACE;
+ }
+
+ return AddRef(), S_OK;
+}
+
+#endif /* _WIN32_WCE */
diff --git a/plugins/pluginDirectShow/internals/wince/CPropertyBag.h b/plugins/pluginDirectShow/internals/wince/CPropertyBag.h
new file mode 100644
index 0000000..20ce779
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/wince/CPropertyBag.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#if defined(_WIN32_WCE)
+
+#include "plugin_dshow_config.h"
+
+struct VAR_LIST
+{
+ VARIANT var;
+ VAR_LIST *pNext;
+ BSTR pBSTRName;
+};
+
+class CPropertyBag : public IPropertyBag
+{
+public:
+ CPropertyBag();
+ ~CPropertyBag();
+
+ HRESULT STDMETHODCALLTYPE
+ Read(
+ LPCOLESTR pszPropName,
+ VARIANT *pVar,
+ IErrorLog *pErrorLog
+ );
+
+
+ HRESULT STDMETHODCALLTYPE
+ Write(
+ LPCOLESTR pszPropName,
+ VARIANT *pVar
+ );
+
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv);
+
+private:
+ ULONG _refCount;
+ VAR_LIST *pVar;
+};
+
+#endif /* _WIN32_WCE */
diff --git a/plugins/pluginDirectShow/internals/wince/DSISampleGrabberCB.h b/plugins/pluginDirectShow/internals/wince/DSISampleGrabberCB.h
new file mode 100644
index 0000000..89d8909
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/wince/DSISampleGrabberCB.h
@@ -0,0 +1,30 @@
+/* Copyright (C) 2014-2015 Mamadou DIOP
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#pragma once
+
+#if defined(_WIN32_WCE)
+
+#include "plugin_dshow_config.h"
+
+interface DSISampleGrabberCB
+{
+ virtual HRESULT STDMETHODCALLTYPE SampleCB(double SampleTime, IMediaSample *pSample) = 0;
+ virtual HRESULT STDMETHODCALLTYPE BufferCB(double SampleTime, BYTE *pBuffer, long BufferLen) = 0;
+};
+
+#endif /* _WIN32_WCE */ \ No newline at end of file
diff --git a/plugins/pluginDirectShow/internals/wince/DSNullFilter.cxx b/plugins/pluginDirectShow/internals/wince/DSNullFilter.cxx
new file mode 100644
index 0000000..76d713c
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/wince/DSNullFilter.cxx
@@ -0,0 +1,56 @@
+#if defined(_WIN32_WCE)
+
+/* Copyright (C) 2014-2015 Mamadou DIOP
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+
+#include "internals/wince/DSNullFilter.h"
+
+// {7F9F08CF-139F-40b2-A283-01C4EC26A452}
+TDSHOW_DEFINE_GUID(CLSID_DSNullFilter,
+0x7f9f08cf, 0x139f, 0x40b2, 0xa2, 0x83, 0x1, 0xc4, 0xec, 0x26, 0xa4, 0x52);
+
+DSNullFilter::DSNullFilter(LPUNKNOWN punk,HRESULT *phr)
+ : CTransInPlaceFilter(TEXT("NullRenderer"), punk, CLSID_DSNullFilter, phr)
+{
+}
+
+HRESULT DSNullFilter::CheckInputType(const CMediaType *mtIn)
+{
+ CheckPointer(mtIn,E_POINTER);
+
+ if (*mtIn->FormatType() != FORMAT_VideoInfo) {
+ return E_INVALIDARG;
+ }
+
+ if ( *mtIn->Type( ) != MEDIATYPE_Video ) {
+ return E_INVALIDARG;
+ }
+
+ if ( *mtIn->Subtype( ) != MEDIASUBTYPE_RGB24 ) {
+ return E_INVALIDARG;
+ }
+
+ return NOERROR;
+}
+
+HRESULT DSNullFilter::Transform(IMediaSample *pSample)
+{
+ return NOERROR;
+}
+
+#endif /* _WIN32_WCE */
diff --git a/plugins/pluginDirectShow/internals/wince/DSNullFilter.h b/plugins/pluginDirectShow/internals/wince/DSNullFilter.h
new file mode 100644
index 0000000..fc9b76a
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/wince/DSNullFilter.h
@@ -0,0 +1,40 @@
+/* Copyright (C) 2014-2015 Mamadou DIOP
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#pragma once
+
+#if defined(_WIN32_WCE)
+
+#include "plugin_dshow_config.h"
+
+#include <streams.h>
+#include <math.h>
+
+class DSNullFilter : public CTransInPlaceFilter
+{
+public:
+
+ DECLARE_IUNKNOWN;
+
+ HRESULT Transform(IMediaSample *pSample);
+ HRESULT CheckInputType(const CMediaType *mtIn);
+
+ // Constructor
+ DSNullFilter( LPUNKNOWN punk, HRESULT *phr );
+};
+
+#endif /* _WIN32_WCE */
diff --git a/plugins/pluginDirectShow/internals/wince/DSSampleGrabber.cxx b/plugins/pluginDirectShow/internals/wince/DSSampleGrabber.cxx
new file mode 100644
index 0000000..d33d105
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/wince/DSSampleGrabber.cxx
@@ -0,0 +1,197 @@
+#if defined(_WIN32_WCE)
+
+#include <ddraw.h>
+#include <internals/wince/DSSampleGrabber.h>
+#include <initguid.h>
+
+
+// {38589364-71FD-4641-B426-E443DB023568}
+TDSHOW_DEFINE_GUID(CLSID_SampleGrabber,
+0x38589364, 0x71fd, 0x4641, 0xb4, 0x26, 0xe4, 0x43, 0xdb, 0x2, 0x35, 0x68);
+
+#define RGB565_MASK_RED 0xF800
+#define RGB565_MASK_GREEN 0x07E0
+#define RGB565_MASK_BLUE 0x001F
+
+DSSampleGrabber::DSSampleGrabber(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr)
+:CTransInPlaceFilter (tszName, punk, CLSID_SampleGrabber, phr)
+{
+#define FPS_INPUT 30
+#define FPS_OUTPUT 5
+
+ this->m_rtFrameLength = (10000000)/FPS_OUTPUT;
+
+ this->m_inputFps = FPS_INPUT;
+ this->m_outputFps = FPS_OUTPUT;
+
+ this->m_iFrameNumber = 0;
+ this->m_progress = 0;
+ this->m_bProcessFrame = true;
+
+ this->callback = NULL;
+ this->m_rgb24 = NULL;
+
+ m_cRef = 0;
+}
+
+DSSampleGrabber::~DSSampleGrabber() {
+ this->callback = NULL;
+ if(this->m_rgb24)
+ {
+ delete[]this->m_rgb24;
+ this->m_rgb24 = NULL;
+ }
+}
+
+HRESULT DSSampleGrabber::SetFps(int inputFps, int outputFps)
+{
+ if (inputFps <= 0 || outputFps <= 0) {
+ return E_FAIL;
+ }
+
+ // Stop prcessing
+ this->m_bProcessFrame = false;
+
+ if (inputFps < outputFps) {
+ this->m_inputFps = this->m_outputFps = inputFps;
+ }
+ else {
+ this->m_outputFps = outputFps;
+ this->m_inputFps = inputFps;
+ }
+
+ // Restart processing
+ this->m_iFrameNumber = 0;
+ this->m_progress = 0;
+ this->m_bProcessFrame = true;
+
+ return S_OK;
+}
+
+HRESULT DSSampleGrabber::Transform(IMediaSample *pSample)
+{
+ BYTE *pData = NULL;
+ HRESULT hr = S_OK;
+ HRESULT ret = S_FALSE;
+
+ if (!this->m_bProcessFrame) {
+ return S_FALSE;
+ }
+
+ // Get pointer to the video buffer data
+ if ( FAILED(pSample->GetPointer(&pData)) ) {
+ ret = E_FAIL;
+ goto bail;
+ }
+
+ pSample->SetTime(NULL, NULL);
+
+ // Drop frame?
+ if (this->m_iFrameNumber == 0) {
+ ret = S_OK;
+ }
+ else if (this->m_progress >= this->m_inputFps) {
+ this->m_progress -= this->m_inputFps;
+ ret = S_OK;
+ }
+
+ // Mark frame as accepted
+ if (ret == S_OK) {
+ // Set TRUE on every sample for uncompressed frames
+ pSample->SetSyncPoint(TRUE);
+
+ long Size = pSample->GetSize();
+ if ( this->callback ) {
+ LONGLONG start, end;
+ WORD *rgb565 = (WORD*)pData;
+
+ for(int i = 0, i24 = 0, i565 = 0; i< (Size/2); i++, i24+=3, i565+=1) {
+ BYTE *p24 = (this->m_rgb24+i24);
+ WORD val565 = *(rgb565 + i565);
+
+ // extract RGB
+ p24[2] = (val565 & RGB565_MASK_RED) >> 11;
+ p24[1] = (val565 & RGB565_MASK_GREEN) >> 5;
+ p24[0] = (val565 & RGB565_MASK_BLUE);
+
+ // amplify the image
+ p24[2] <<= 3;
+ p24[1] <<= 2;
+ p24[0] <<= 3;
+ }
+
+ pSample->GetMediaTime(&start, &end);
+ this->callback->BufferCB( (double)start, this->m_rgb24, ((Size >> 1) * 3));
+ }
+ }
+
+ this->m_progress += this->m_outputFps;
+ this->m_iFrameNumber++;
+
+bail:
+ SAFE_DELETE_ARRAY( pData );
+ SAFE_RELEASE(pSample);
+
+ return ret;
+}
+
+HRESULT DSSampleGrabber::CheckInputType(const CMediaType* mtIn)
+{
+ VIDEOINFO *video;
+ if ( !IsEqualGUID( *mtIn->Subtype(), MEDIASUBTYPE_RGB565 ) || !(video=(VIDEOINFO *)mtIn->Format()) ) {
+ return E_FAIL;
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP DSSampleGrabber::SetCallback( DSISampleGrabberCB* callback_ )
+{
+ if (!callback_) {
+ return E_FAIL;
+ }
+
+ this->callback = callback_;
+ return S_OK;
+}
+
+HRESULT DSSampleGrabber::SetSize(int width, int height)
+{
+ ZeroMemory(&this->mt, sizeof(CMediaType));
+
+ VIDEOINFO *pvi = (VIDEOINFO *)this->mt.AllocFormatBuffer(sizeof(VIDEOINFO));
+ if (NULL == pvi)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ ZeroMemory(pvi, sizeof(VIDEOINFO));
+
+ pvi->bmiHeader.biCompression = BI_RGB;
+ pvi->bmiHeader.biBitCount = 24;
+ pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pvi->bmiHeader.biWidth = width;
+ pvi->bmiHeader.biHeight = height;
+ pvi->bmiHeader.biPlanes = 1;
+ pvi->bmiHeader.biSizeImage = GetBitmapSize(&pvi->bmiHeader);
+ pvi->bmiHeader.biClrImportant = 0;
+
+ // Frame rate
+ pvi->AvgTimePerFrame = 10000000/this->m_outputFps;
+
+ SetRectEmpty(&(pvi->rcSource)); // we want the whole image area rendered.
+ SetRectEmpty(&(pvi->rcTarget)); // no particular destination rectangle
+
+ this->mt.SetType(&MEDIATYPE_Video);
+ this->mt.SetFormatType(&FORMAT_VideoInfo);
+ this->mt.SetTemporalCompression(FALSE);
+
+ this->mt.SetSubtype(&MEDIASUBTYPE_RGB24);
+ this->mt.SetSampleSize(pvi->bmiHeader.biSizeImage);
+
+ this->m_rgb24 = new BYTE[pvi->bmiHeader.biSizeImage];
+
+ return S_OK;
+}
+
+#endif /* _WIN32_WCE */
diff --git a/plugins/pluginDirectShow/internals/wince/DSSampleGrabber.h b/plugins/pluginDirectShow/internals/wince/DSSampleGrabber.h
new file mode 100644
index 0000000..39ee5c6
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/wince/DSSampleGrabber.h
@@ -0,0 +1,73 @@
+/* Copyright (C) 2014-2015 Mamadou DIOP
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+
+#pragma once
+
+#if defined(_WIN32_WCE)
+
+#include "plugin_dshow_config.h"
+
+#include <streams.h>
+#include <math.h>
+
+#include <internals/DSUtils.h>
+#include <internals/wince/DSISampleGrabberCB.h>
+#include "DSSampleGrabberUtils.h"
+
+class DSSampleGrabber : public CTransInPlaceFilter
+{
+public:
+ // instantiation
+ DSSampleGrabber( TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr );
+ ~DSSampleGrabber(void);
+
+public:
+ HRESULT Transform(IMediaSample *pSample);
+ HRESULT CheckInputType(const CMediaType* mtIn);
+
+ HRESULT SetFps(int inputFps, int outputFps);
+
+ // DECLARE_IUNKNOWN;
+ STDMETHODIMP QueryInterface(REFIID riid, void **ppv) {
+ return GetOwner()->QueryInterface(riid,ppv);
+ };
+ STDMETHODIMP_(ULONG) AddRef() {
+ return InterlockedIncrement(&m_cRef);
+ };
+ STDMETHODIMP_(ULONG) Release() {
+ return GetOwner()->Release();
+ };
+
+ STDMETHODIMP SetCallback(DSISampleGrabberCB* callback_);
+ HRESULT SetSize(int width, int height);
+
+ inline AM_MEDIA_TYPE GetMediaType() { return (AM_MEDIA_TYPE)this->mt; }
+
+private:
+ int m_progress;
+ int m_inputFps, m_outputFps;
+ bool m_bProcessFrame;
+ REFERENCE_TIME m_rtFrameLength; // UNITS/fps
+ LONGLONG m_iFrameNumber;
+
+ DSISampleGrabberCB* callback;
+ CMediaType mt;
+ BYTE *m_rgb24;
+};
+
+#endif /* _WIN32_WCE */
diff --git a/plugins/pluginDirectShow/internals/wince/DSSampleGrabberUtils.h b/plugins/pluginDirectShow/internals/wince/DSSampleGrabberUtils.h
new file mode 100644
index 0000000..01e1728
--- /dev/null
+++ b/plugins/pluginDirectShow/internals/wince/DSSampleGrabberUtils.h
@@ -0,0 +1,38 @@
+/* Copyright (C) 2014-2015 Mamadou DIOP
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*/
+#pragma once
+
+#if defined(_WIN32_WCE)
+
+// callback definition
+typedef void (CALLBACK *MANAGEDCALLBACKPROC)(BYTE* pdata, long len);
+
+// ISampleGrabber interface definition
+
+// {04951BFF-696A-4ade-828D-42A5F1EDB631}
+DEFINE_GUID(IID_ISampleGrabber,
+ 0x4951bff, 0x696a, 0x4ade, 0x82, 0x8d, 0x42, 0xa5, 0xf1, 0xed, 0xb6, 0x31);
+
+DECLARE_INTERFACE_(ISampleGrabber, IUnknown) {
+ STDMETHOD(SetCallback)(MANAGEDCALLBACKPROC callback) PURE;};
+
+ // {D11DFE19-8864-4a60-B26C-552F9AA472E1}
+DEFINE_GUID(CLSID_NullRenderer,
+ 0xd11dfe19, 0x8864, 0x4a60, 0xb2, 0x6c, 0x55, 0x2f, 0x9a, 0xa4, 0x72, 0xe1);
+
+#endif /* _WIN32_WCE */
OpenPOWER on IntegriCloud