summaryrefslogtreecommitdiffstats
path: root/tinyDSHOW
diff options
context:
space:
mode:
Diffstat (limited to 'tinyDSHOW')
-rw-r--r--tinyDSHOW/include/tinydshow/DSBufferWriter.h52
-rw-r--r--tinyDSHOW/include/tinydshow/DSCaptureFormat.h51
-rw-r--r--tinyDSHOW/include/tinydshow/DSCaptureGraph.h108
-rw-r--r--tinyDSHOW/include/tinydshow/DSCaptureUtils.h64
-rw-r--r--tinyDSHOW/include/tinydshow/DSDisplay.h80
-rw-r--r--tinyDSHOW/include/tinydshow/DSDisplayGraph.h107
-rw-r--r--tinyDSHOW/include/tinydshow/DSDisplayOverlay.h72
-rw-r--r--tinyDSHOW/include/tinydshow/DSFrameRateFilter.h83
-rw-r--r--tinyDSHOW/include/tinydshow/DSGrabber.h91
-rw-r--r--tinyDSHOW/include/tinydshow/DSOutputFilter.h127
-rw-r--r--tinyDSHOW/include/tinydshow/DSOutputStream.h95
-rw-r--r--tinyDSHOW/include/tinydshow/DSUtils.h78
-rw-r--r--tinyDSHOW/include/tinydshow/Resizer.h174
-rw-r--r--tinyDSHOW/include/tinydshow/VideoDisplayName.h47
-rw-r--r--tinyDSHOW/include/tinydshow/VideoFrame.h108
-rw-r--r--tinyDSHOW/include/tinydshow/VideoGrabberName.h47
-rw-r--r--tinyDSHOW/include/tinydshow/plugin/DSConsumer.h35
-rw-r--r--tinyDSHOW/include/tinydshow/plugin/DSProducer.h35
-rw-r--r--tinyDSHOW/include/tinydshow_config.h61
-rw-r--r--tinyDSHOW/src/DSCaptureFormat.cxx64
-rw-r--r--tinyDSHOW/src/DSCaptureGraph.cxx443
-rw-r--r--tinyDSHOW/src/DSCaptureUtils.cxx376
-rw-r--r--tinyDSHOW/src/DSDisplay.cxx581
-rw-r--r--tinyDSHOW/src/DSDisplayGraph.cxx330
-rw-r--r--tinyDSHOW/src/DSDisplayOverlay.VMR.cxx179
-rw-r--r--tinyDSHOW/src/DSDisplayOverlay.VMR9.cxx211
-rw-r--r--tinyDSHOW/src/DSDisplayOverlay.cxx71
-rw-r--r--tinyDSHOW/src/DSFrameRateFilter.cxx126
-rw-r--r--tinyDSHOW/src/DSGrabber.cxx255
-rw-r--r--tinyDSHOW/src/DSOutputFilter.cxx113
-rw-r--r--tinyDSHOW/src/DSOutputStream.cxx308
-rw-r--r--tinyDSHOW/src/DSUtils.cxx155
-rw-r--r--tinyDSHOW/src/Resizer.cxx1097
-rw-r--r--tinyDSHOW/src/VideoDisplayName.cxx41
-rw-r--r--tinyDSHOW/src/VideoGrabberName.cxx41
-rw-r--r--tinyDSHOW/src/plugin/DSConsumer.cxx278
-rw-r--r--tinyDSHOW/src/plugin/DSProducer.cxx278
-rw-r--r--tinyDSHOW/tinyDSHOW.vcproj348
38 files changed, 6810 insertions, 0 deletions
diff --git a/tinyDSHOW/include/tinydshow/DSBufferWriter.h b/tinyDSHOW/include/tinydshow/DSBufferWriter.h
new file mode 100644
index 0000000..156471f
--- /dev/null
+++ b/tinyDSHOW/include/tinydshow/DSBufferWriter.h
@@ -0,0 +1,52 @@
+/*
+* Copyright (C) 2009-2010 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 DSBUFFERWRITTER_H
+#define 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/tinyDSHOW/include/tinydshow/DSCaptureFormat.h b/tinyDSHOW/include/tinydshow/DSCaptureFormat.h
new file mode 100644
index 0000000..5eb372d
--- /dev/null
+++ b/tinyDSHOW/include/tinydshow/DSCaptureFormat.h
@@ -0,0 +1,51 @@
+/*
+* Copyright (C) 2009-2010 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 DSCAPTUREFORMAT_H
+#define DSCAPTUREFORMAT_H
+
+#include <tinydshow_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/tinyDSHOW/include/tinydshow/DSCaptureGraph.h b/tinyDSHOW/include/tinydshow/DSCaptureGraph.h
new file mode 100644
index 0000000..b3eac91
--- /dev/null
+++ b/tinyDSHOW/include/tinydshow/DSCaptureGraph.h
@@ -0,0 +1,108 @@
+/*
+* Copyright (C) 2009-2010 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 DSCAPTUREGRAPH_H
+#define DSCAPTUREGRAPH_H
+
+#include <tinydshow_config.h>
+#include <vector>
+#include <control.h>
+#include <tinydshow/DSCaptureFormat.h>
+#include <tinydshow/DSFrameRateFilter.h>
+
+#ifdef _WIN32_WCE
+# include <tinydshow/wce/DSSampleGrabber.h>
+# include <tinydshow/wce/DSInxbNullFilter.h>
+# include <tinydshow/wce/InxbISampleGrabberCB.h>
+#else
+# include <qedit.h>
+#endif
+
+
+class DSCaptureGraph
+{
+public:
+#ifdef _WIN32_WCE
+ DSCaptureGraph(InxbISampleGrabberCB* 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();
+ bool isRunning();
+
+ std::string getDeviceId() const { return this->deviceId; };
+
+ HRESULT getConnectedMediaType(AM_MEDIA_TYPE *mediaType);
+
+private:
+ HRESULT createCaptureGraph();
+
+private:
+#ifdef _WIN32_WCE
+ InxbISampleGrabberCB *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
+ IBaseFilter *decompressorFilter;
+ 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;
+ std::string deviceId;
+};
+
+#endif
diff --git a/tinyDSHOW/include/tinydshow/DSCaptureUtils.h b/tinyDSHOW/include/tinydshow/DSCaptureUtils.h
new file mode 100644
index 0000000..33f0640
--- /dev/null
+++ b/tinyDSHOW/include/tinydshow/DSCaptureUtils.h
@@ -0,0 +1,64 @@
+/*
+* Copyright (C) 2009-2010 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 DSCAPTUREUTILS_H
+#define DSCAPTUREUTILS_H
+
+#include <tinydshow_config.h>
+#include <tinydshow/DSCaptureFormat.h>
+#include <tinydshow/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/tinyDSHOW/include/tinydshow/DSDisplay.h b/tinyDSHOW/include/tinydshow/DSDisplay.h
new file mode 100644
index 0000000..aaf8258
--- /dev/null
+++ b/tinyDSHOW/include/tinydshow/DSDisplay.h
@@ -0,0 +1,80 @@
+/*
+* Copyright (C) 2009-2010 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 DIRECTSHOW_DISPLAY_H
+#define DIRECTSHOW_DISPLAY_H
+
+#include <tinydshow_config.h>
+
+#include <tinydshow/DSDisplayGraph.h>
+#include <tinydshow/DSDisplayOverlay.h>
+
+
+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 stop();
+
+ virtual int getWidth();
+ virtual int getHeight();
+ virtual void setSize(int w, int h);
+
+ virtual bool isFullscreen();
+ virtual void setFullscreen(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 width, height;
+
+ bool fullscreen;
+ HWND window;
+ WNDPROC parentWindowProc;
+
+ bool hooked;
+};
+
+#endif
diff --git a/tinyDSHOW/include/tinydshow/DSDisplayGraph.h b/tinyDSHOW/include/tinydshow/DSDisplayGraph.h
new file mode 100644
index 0000000..32942be
--- /dev/null
+++ b/tinyDSHOW/include/tinydshow/DSDisplayGraph.h
@@ -0,0 +1,107 @@
+/*
+* Copyright (C) 2009-2010 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 DSDISPLAYGRAPH_H
+#define DSDISPLAYGRAPH_H
+
+#include <tinydshow_config.h>
+
+#include <control.h>
+
+#include <tinydshow/VideoFrame.h>
+#include <tinydshow/DSOutputFilter.h>
+#include <tinydshow/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 stop();
+ bool isRunning();
+
+ 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;
+ int fps;
+};
+
+#endif
diff --git a/tinyDSHOW/include/tinydshow/DSDisplayOverlay.h b/tinyDSHOW/include/tinydshow/DSDisplayOverlay.h
new file mode 100644
index 0000000..539a5bc
--- /dev/null
+++ b/tinyDSHOW/include/tinydshow/DSDisplayOverlay.h
@@ -0,0 +1,72 @@
+/*
+* Copyright (C) 2009-2010 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 DSDISPLAYOVERLAY_H
+#define DSDISPLAYOVERLAY_H
+
+#include <tinydshow_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/tinyDSHOW/include/tinydshow/DSFrameRateFilter.h b/tinyDSHOW/include/tinydshow/DSFrameRateFilter.h
new file mode 100644
index 0000000..78aa88e
--- /dev/null
+++ b/tinyDSHOW/include/tinydshow/DSFrameRateFilter.h
@@ -0,0 +1,83 @@
+/*
+* Copyright (C) 2009-2010 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 DSFrameRateFilter_H
+#define DSFrameRateFilter_H
+
+#include <tinydshow_config.h>
+
+#include <streams.h>
+#include <math.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
+
+// {7F9F08CF-139F-40b2-A283-01C4EC26A452}
+TDSHOW_DEFINE_GUID(CLSID_DSFrameRateFilter,
+0x7f9f08cf, 0x139f, 0x40b2, 0xa2, 0x83, 0x1, 0xc4, 0xec, 0x26, 0xa4, 0x52);
+
+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/tinyDSHOW/include/tinydshow/DSGrabber.h b/tinyDSHOW/include/tinydshow/DSGrabber.h
new file mode 100644
index 0000000..4c66716
--- /dev/null
+++ b/tinyDSHOW/include/tinydshow/DSGrabber.h
@@ -0,0 +1,91 @@
+/*
+* Copyright (C) 2009-2010 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(DIRECTSHOW_GRABBER_H)/* && !defined(_WIN32_WCE)*/
+#define DIRECTSHOW_GRABBER_H
+
+#include <tinydshow_config.h>
+
+#include <tinydshow/DSCaptureGraph.h>
+#include <tinydshow/VideoFrame.h>
+
+#include "tinymedia/tmedia_producer.h"
+
+#include "tsk_mutex.h"
+
+class DSDisplay;
+
+#ifdef _WIN32_WCE
+# include <tinydshow/wce/InxbISampleGrabberCB.h>
+#endif
+
+
+class DSGrabber : public
+#ifdef _WIN32_WCE
+ InxbISampleGrabberCB
+#else
+ ISampleGrabberCB
+#endif
+{
+public:
+ DSGrabber(HRESULT *hr);
+ 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 stop();
+
+ virtual bool setCaptureParameters(int format, int f);
+
+ virtual VIDEOFORMAT getCaptureFormat();
+ virtual int getFramerate();
+
+ 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;
+
+ DSCaptureGraph *graph;
+
+ //VideoFrame *currentFrame;
+ BITMAPINFOHEADER bitmapInfo;
+ BYTE *buffer;
+
+ tsk_mutex_handle_t *mutex_buffer;
+
+ bool first_buffer;
+
+ const void* plugin_cb_data;
+ tmedia_producer_enc_cb_f plugin_cb;
+};
+
+#endif
diff --git a/tinyDSHOW/include/tinydshow/DSOutputFilter.h b/tinyDSHOW/include/tinydshow/DSOutputFilter.h
new file mode 100644
index 0000000..1e141b3
--- /dev/null
+++ b/tinyDSHOW/include/tinydshow/DSOutputFilter.h
@@ -0,0 +1,127 @@
+/*
+* Copyright (C) 2009-2010 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 DSOUTPUTFILTER_H
+#define DSOUTPUTFILTER_H
+
+#include <tinydshow_config.h>
+
+#include <tinydshow/DSBufferWriter.h>
+#include <streams.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
+
+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/tinyDSHOW/include/tinydshow/DSOutputStream.h b/tinyDSHOW/include/tinydshow/DSOutputStream.h
new file mode 100644
index 0000000..d786922
--- /dev/null
+++ b/tinyDSHOW/include/tinydshow/DSOutputStream.h
@@ -0,0 +1,95 @@
+/*
+* Copyright (C) 2009-2010 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 DSOUTPUTSTREAM_H
+#define DSOUTPUTSTREAM_H
+
+#include <tinydshow_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 */void TransfertBuffer(void* src, void* dest, long lSize);
+ 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/tinyDSHOW/include/tinydshow/DSUtils.h b/tinyDSHOW/include/tinydshow/DSUtils.h
new file mode 100644
index 0000000..957954b
--- /dev/null
+++ b/tinyDSHOW/include/tinydshow/DSUtils.h
@@ -0,0 +1,78 @@
+/*
+* Copyright (C) 2009-2010 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 TINYDSHOW_DUTILS_H
+#define TINYDSHOW_DUTILS_H
+
+#include <tinydshow_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; }
+
+#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_100NS_TO_SECONDS(NANOS) (((LONGLONG)(NANOS)) / 10000000ui64)
+
+//#define SECONDS_TO_100NS(s) (LONGLONG)(10000000/(s))
+//#define SECONDS_FROM_100NS(ns) (10000000/(ns))
+
+#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_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")
+
+// --------------------------------------------------------------------------------
+
+bool IsMainThread();
+
+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);
+
+#endif /* TINYDSHOW_DUTILS_H */
diff --git a/tinyDSHOW/include/tinydshow/Resizer.h b/tinyDSHOW/include/tinydshow/Resizer.h
new file mode 100644
index 0000000..d5ef36e
--- /dev/null
+++ b/tinyDSHOW/include/tinydshow/Resizer.h
@@ -0,0 +1,174 @@
+/*
+* Copyright (C) 2009-2010 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.
+*
+*/
+/*
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ */
+#ifndef RESIZER_H
+#define RESIZER_H
+
+#include <tinydshow_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>
+
+/* 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
+ );
+
+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
+
+/*
+* 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);
+
+#endif //RESIZER_H
diff --git a/tinyDSHOW/include/tinydshow/VideoDisplayName.h b/tinyDSHOW/include/tinydshow/VideoDisplayName.h
new file mode 100644
index 0000000..65044db
--- /dev/null
+++ b/tinyDSHOW/include/tinydshow/VideoDisplayName.h
@@ -0,0 +1,47 @@
+/*
+* Copyright (C) 2009-2010 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 TINYDSHOW_VIDEODISPLAYNAME_H
+#define TINYDSHOW_VIDEODISPLAYNAME_H
+
+#include "tinydshow_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 /* TINYDSHOW_VIDEODISPLAYNAME_H */
diff --git a/tinyDSHOW/include/tinydshow/VideoFrame.h b/tinyDSHOW/include/tinydshow/VideoFrame.h
new file mode 100644
index 0000000..8722083
--- /dev/null
+++ b/tinyDSHOW/include/tinydshow/VideoFrame.h
@@ -0,0 +1,108 @@
+/*
+* Copyright (C) 2009-2010 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 VIDEOFRAME_H
+#define 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_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_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 == 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/tinyDSHOW/include/tinydshow/VideoGrabberName.h b/tinyDSHOW/include/tinydshow/VideoGrabberName.h
new file mode 100644
index 0000000..5a2344c
--- /dev/null
+++ b/tinyDSHOW/include/tinydshow/VideoGrabberName.h
@@ -0,0 +1,47 @@
+/*
+* Copyright (C) 2009-2010 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 TINYDSHOW_VIDEOGRABBERNAME_H
+#define TINYDSHOW_VIDEOGRABBERNAME_H
+
+#include "tinydshow_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 /* TINYDSHOW_VIDEOGRABBERNAME_H */
diff --git a/tinyDSHOW/include/tinydshow/plugin/DSConsumer.h b/tinyDSHOW/include/tinydshow/plugin/DSConsumer.h
new file mode 100644
index 0000000..36fb413
--- /dev/null
+++ b/tinyDSHOW/include/tinydshow/plugin/DSConsumer.h
@@ -0,0 +1,35 @@
+/*
+* Copyright (C) 2009-2010 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 DSCONSUMER_H
+#define DSCONSUMER_H
+
+#include <tinydshow_config.h>
+
+#include "tinymedia/tmedia_consumer.h"
+
+TDSHOW_BEGIN_DECLS
+
+TINYDSHOW_GEXTERN const tmedia_consumer_plugin_def_t *tdshow_consumer_plugin_def_t;
+
+TDSHOW_END_DECLS
+
+#endif /* DSCONSUMER_H */
diff --git a/tinyDSHOW/include/tinydshow/plugin/DSProducer.h b/tinyDSHOW/include/tinydshow/plugin/DSProducer.h
new file mode 100644
index 0000000..6af7e79
--- /dev/null
+++ b/tinyDSHOW/include/tinydshow/plugin/DSProducer.h
@@ -0,0 +1,35 @@
+/*
+* Copyright (C) 2009-2010 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 DSPRODUCER_H
+#define DSPRODUCER_H
+
+#include <tinydshow_config.h>
+
+#include "tinymedia/tmedia_producer.h"
+
+TDSHOW_BEGIN_DECLS
+
+TINYDSHOW_GEXTERN const tmedia_producer_plugin_def_t *tdshow_producer_plugin_def_t;
+
+TDSHOW_END_DECLS
+
+#endif /* DSPRODUCER_H */
diff --git a/tinyDSHOW/include/tinydshow_config.h b/tinyDSHOW/include/tinydshow_config.h
new file mode 100644
index 0000000..8997c0d
--- /dev/null
+++ b/tinyDSHOW/include/tinydshow_config.h
@@ -0,0 +1,61 @@
+/*
+* Copyright (C) 2009-2010 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 TINYDSHOW_CONFIG_H
+#define TINYDSHOW_CONFIG_H
+
+#include <windows.h>
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <memory.h>
+#include <tchar.h>
+
+
+#if defined(TINYDSHOW_EXPORTS)
+# define TINYDSHOW_API __declspec(dllexport)
+# define TINYDSHOW_GEXTERN __declspec(dllexport)
+#else
+# define TINYDSHOW_API __declspec(dllimport)
+# define TINYDSHOW_GEXTERN __declspec(dllimport)
+#endif
+
+/* Guards against C++ name mangling */
+#ifdef __cplusplus
+# define TDSHOW_BEGIN_DECLS extern "C" {
+# define TDSHOW_END_DECLS }
+#else
+# define TDSHOW_BEGIN_DECLS
+# define TDSHOW_END_DECLS
+#endif
+
+/* Disable some well-known warnings */
+#ifdef _MSC_VER
+# pragma warning (disable:4995 4996)
+# define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#if HAVE_CONFIG_H
+ #include "../config.h"
+#endif
+
+#endif // TINYDSHOW_CONFIG_H
diff --git a/tinyDSHOW/src/DSCaptureFormat.cxx b/tinyDSHOW/src/DSCaptureFormat.cxx
new file mode 100644
index 0000000..844f917
--- /dev/null
+++ b/tinyDSHOW/src/DSCaptureFormat.cxx
@@ -0,0 +1,64 @@
+/*
+* Copyright (C) 2009-2010 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 <tinydshow/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/tinyDSHOW/src/DSCaptureGraph.cxx b/tinyDSHOW/src/DSCaptureGraph.cxx
new file mode 100644
index 0000000..8c89d9f
--- /dev/null
+++ b/tinyDSHOW/src/DSCaptureGraph.cxx
@@ -0,0 +1,443 @@
+/*
+* Copyright (C) 2009-2010 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 <tinydshow/DSCaptureGraph.h>
+#include <tinydshow/DSUtils.h>
+#include <tinydshow/DSCaptureUtils.h>
+
+#include "tsk_debug.h"
+
+#include <iostream>
+
+using namespace std;
+
+#ifdef _WIN32_WCE
+DSCaptureGraph::DSCaptureGraph(InxbISampleGrabberCB* callback, HRESULT *hr)
+#else
+DSCaptureGraph::DSCaptureGraph(ISampleGrabberCB* callback, HRESULT *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;
+ this->decompressorFilter = NULL;
+#endif
+
+ this->nullRendererFilter = NULL;
+ this->grabberController = NULL;
+ this->mediaController = NULL;
+ this->mediaEventController = NULL;
+
+ this->streamConfiguration = NULL;
+
+ this->running = FALSE;
+ this->deviceId = "";
+
+ *hr = this->createCaptureGraph();
+}
+
+DSCaptureGraph::~DSCaptureGraph()
+{
+ SAFE_RELEASE(this->streamConfiguration);
+
+ SAFE_RELEASE(this->mediaEventController);
+ SAFE_RELEASE(this->mediaController);
+ SAFE_RELEASE(this->grabberController);
+
+#ifdef _WIN32_WCE
+ SAFE_RELEASE(this->colorConvertor565);
+#else
+ SAFE_RELEASE(this->decompressorFilter);
+#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;
+
+#ifdef _WIN32_WCE
+ hr = this->grabberController->SetFps((int) 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;
+}
+
+#ifdef _WIN32_WCE
+# include <tinydshow/wce/DSInxbNullFilter.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->captureFormat->isRGB())
+ {
+#if _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
+ hr = ConnectFilters(this->graphBuilder, this->sourceFilter, this->frameRateFilter); if(FAILED(hr))return hr;
+ hr = ConnectFilters(this->graphBuilder, this->frameRateFilter, this->sampleGrabberFilter); if(FAILED(hr))return hr;
+ hr = ConnectFilters(this->graphBuilder, this->sampleGrabberFilter, this->nullRendererFilter); if(FAILED(hr))return hr;
+#endif
+ }
+ else
+ {
+#ifdef _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
+ hr = ConnectFilters(this->graphBuilder, this->sourceFilter, this->decompressorFilter); if(FAILED(hr))return hr;
+ hr = ConnectFilters(this->graphBuilder, this->decompressorFilter, this->frameRateFilter); if(FAILED(hr))return hr;
+ hr = ConnectFilters(this->graphBuilder, this->frameRateFilter, this->sampleGrabberFilter); if(FAILED(hr))return hr;
+ hr = ConnectFilters(this->graphBuilder, this->sampleGrabberFilter, this->nullRendererFilter); if(FAILED(hr))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())
+ {
+#ifdef _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
+ {
+#ifdef _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->decompressorFilter);
+ hr = DisconnectFilters(this->graphBuilder, this->decompressorFilter, 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(this->running) return S_OK;
+
+ //this->mediaController->Stop();
+
+ hr = this->mediaController->Run();
+ /*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))
+ {
+#ifdef _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);
+ }
+ this->running = true;
+ return hr;
+}
+
+HRESULT DSCaptureGraph::stop()
+{
+ HRESULT hr;
+ 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);
+ }
+ hr = this->mediaController->Stop();
+ if (!SUCCEEDED(hr))
+ {
+ TSK_DEBUG_ERROR("DSCaptureGraph::mediaController->Stop() has failed with %ld", hr);
+ }
+ this->running = false;
+ return hr;
+}
+
+bool DSCaptureGraph::isRunning()
+{
+ return this->running;
+}
+
+HRESULT DSCaptureGraph::getConnectedMediaType(AM_MEDIA_TYPE *mediaType)
+{
+#ifdef _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;
+
+#ifdef _WIN32_WCE
+
+ // Create capture graph builder
+ hr = COCREATE(CLSID_CaptureGraphBuilder, IID_ICaptureGraphBuilder2, this->captureGraphBuilder) ; if(FAILED(hr)) return hr;
+ hr = COCREATE(CLSID_FilterGraph, IID_IGraphBuilder, this->graphBuilder) ; if(FAILED(hr)) return hr;
+ hr = this->captureGraphBuilder->SetFiltergraph(this->graphBuilder) ; if(FAILED(hr)) return hr;
+
+ // Create filters
+ LPUNKNOWN pUnk1 = NULL, pUnk2 = NULL;
+ hr = COCREATE(CLSID_Colour, IID_IBaseFilter, this->colorConvertor565) ;if(FAILED(hr)) return hr;
+ this->sampleGrabberFilter = new DSSampleGrabber(FITLER_SAMPLE_GRABBER, pUnk1, &hr) ;if(FAILED(hr)) return hr;
+ this->nullRendererFilter = new DSInxbNullFilter(/*FILTER_NULL_RENDERER,*/ pUnk2, &hr) ;if(FAILED(hr)) return hr;
+ this->grabberController = (DSSampleGrabber*)(this->sampleGrabberFilter); ;if(!this->grabberController) return E_FAIL;
+
+ // Add Filters
+ hr = this->graphBuilder->AddFilter(this->colorConvertor565, FILTER_COLOR_CONVERTOR_565) ;if(FAILED(hr)) return hr;
+ hr = this->graphBuilder->AddFilter(this->sampleGrabberFilter, FITLER_SAMPLE_GRABBER) ;if(FAILED(hr)) return hr;
+ 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;
+
+ // Set callback
+ hr = this->grabberController->SetCallback(this->grabberCallback);
+ if(FAILED(hr)) return hr;
+#else
+ // 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 the sample grabber filter
+ hr = COCREATE(CLSID_SampleGrabber, IID_IBaseFilter, this->sampleGrabberFilter);
+ if(FAILED(hr)) return hr;
+
+ // Create the AVI decoder filter
+ hr = COCREATE(CLSID_AVIDec, IID_IBaseFilter, this->decompressorFilter);
+ if(FAILED(hr)) return hr;
+
+ // Create tdshow filter
+ LPUNKNOWN pUnk = NULL;
+ this->frameRateFilter = new DSFrameRateFilter(FILTER_FRAMERATE, pUnk, &hr);
+ if(FAILED(hr) || this->frameRateFilter == NULL) return hr;
+
+ // Create the NULL renderer
+ hr = COCREATE(CLSID_NullRenderer, IID_IBaseFilter, this->nullRendererFilter);
+ 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;
+
+ // Add tdshow filter
+ hr = this->graphBuilder->AddFilter(this->frameRateFilter, FILTER_FRAMERATE);
+ if(FAILED(hr)) return hr;
+
+ // Add AVIDec to the graph
+ hr = this->graphBuilder->AddFilter(this->decompressorFilter, FILTER_AVI_DECOMPRESSOR);
+ if(FAILED(hr)) return hr;
+
+ // Find media control
+ hr = QUERY(this->graphBuilder, IID_IMediaControl, this->mediaController);
+ if(FAILED(hr)) return hr;
+
+ // Disable timing
+ /*IMediaFilter *mediaFilterController;
+ hr = QUERY(this->graphBuilder, IID_IMediaFilter, mediaFilterController);
+ if(FAILED(hr)) return hr;
+
+ mediaFilterController->SetSyncSource(NULL);
+ SAFE_RELEASE(mediaFilterController);*/
+
+ // Create the sample grabber
+ 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;
+#endif
+
+ return hr;
+} \ No newline at end of file
diff --git a/tinyDSHOW/src/DSCaptureUtils.cxx b/tinyDSHOW/src/DSCaptureUtils.cxx
new file mode 100644
index 0000000..745473d
--- /dev/null
+++ b/tinyDSHOW/src/DSCaptureUtils.cxx
@@ -0,0 +1,376 @@
+/*
+* Copyright (C) 2009-2010 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 <tinydshow/DSUtils.h>
+#include <tinydshow/DSCaptureUtils.h>
+#include <amvideo.h>
+#include <uuids.h>
+#include <mtype.h>
+
+#include <atlbase.h>
+#include <atlstr.h>
+#include <iostream>
+
+#include "tsk_debug.h"
+
+#ifdef _WIN32_WCE
+# include <internals/wce/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));
+
+#ifdef _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(equals(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/tinyDSHOW/src/DSDisplay.cxx b/tinyDSHOW/src/DSDisplay.cxx
new file mode 100644
index 0000000..9c8c372
--- /dev/null
+++ b/tinyDSHOW/src/DSDisplay.cxx
@@ -0,0 +1,581 @@
+/*
+* Copyright (C) 2009-2010 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 <tinydshow/DSDisplay.h>
+#include <tinydshow/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;
+TINYDSHOW_GEXTERN 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;
+ return (display->hwnd - *((HWND*)hWnd));
+ }
+ return -1;
+}
+
+// C Callback that dispatch event to the right display
+LRESULT CALLBACK __directshow__WndProcWindow(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ LRESULT result = 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(display && display->display){
+ result = display->display->handleEvents(hWnd, uMsg, wParam, lParam);
+ }
+
+ tsk_list_unlock(__directshow__Displays);
+ }
+
+ return result;
+}
+
+
+
+DSDisplay::DSDisplay(HRESULT *hr)
+{
+ this->window = NULL;
+ this->parentWindowProc = NULL;
+ this->hooked = FALSE;
+ this->fullscreen = FALSE;
+ this->width = 176;
+ this->height = 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();
+ this->graph->start();
+ }
+ this->graph->getVideoWindow()->put_Visible(OATRUE);
+}
+
+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 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
+ }
+ }
+}
+
+void DSDisplay::applyRatio(RECT rect)
+{
+ long w = rect.right - rect.left;
+ long h = rect.bottom - rect.top;
+ float ratio = ((float)176/(float)144);//FIXME
+ // (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);
+}
+
+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()){
+ 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
+}
+
+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 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(0, 0, this->width , this->height);
+#endif
+ }
+ break;
+
+ case WM_LBUTTONDBLCLK:
+ if(this->canFullscreen()){
+ this->setFullscreen(true);
+ }
+
+ 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, 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 CallWindowProc(this->parentWindowProc, hWnd, uMsg, wParam, lParam);
+}
+
+void DSDisplay::hook()
+{
+ HRESULT hr;
+
+ if (!this->window){
+ return;
+ }
+
+ if(this->hooked){
+ return;
+ }
+ this->hooked = TRUE;
+
+ 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, GWL_WNDPROC, (LONG) __directshow__WndProcWindow);
+ // Add this instance to the callback map
+ tsk_object_new(tdshow_display_def_t, this->window, this);
+#endif
+ }
+ 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(0, 0, 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
+
+
+ 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, GWL_WNDPROC, (LONG) this->parentWindowProc);
+#endif
+ }
+ 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){
+ return (d1->hwnd - d2->hwnd);
+ }
+ 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/tinyDSHOW/src/DSDisplayGraph.cxx b/tinyDSHOW/src/DSDisplayGraph.cxx
new file mode 100644
index 0000000..58f9533
--- /dev/null
+++ b/tinyDSHOW/src/DSDisplayGraph.cxx
@@ -0,0 +1,330 @@
+/*
+* Copyright (C) 2009-2010 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(VMR9)
+#define DIRECT3D_VERSION 0x0900
+#endif
+
+#include <tinydshow/DSDisplayGraph.h>
+#include <tinydshow/DSUtils.h>
+#include <tinydshow/DSOutputFilter.h>
+
+#include "tsk_debug.h"
+
+#include <iostream>
+
+using namespace std;
+
+DSDisplayGraph::DSDisplayGraph(HRESULT *hr)
+{
+ this->running = 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::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;
+
+ return hr;
+}
+
+bool DSDisplayGraph::isRunning()
+{
+ return this->running;
+}
+
+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/tinyDSHOW/src/DSDisplayOverlay.VMR.cxx b/tinyDSHOW/src/DSDisplayOverlay.VMR.cxx
new file mode 100644
index 0000000..37b0b11
--- /dev/null
+++ b/tinyDSHOW/src/DSDisplayOverlay.VMR.cxx
@@ -0,0 +1,179 @@
+/*
+* Copyright (C) 2009-2010 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/tinyDSHOW/src/DSDisplayOverlay.VMR9.cxx b/tinyDSHOW/src/DSDisplayOverlay.VMR9.cxx
new file mode 100644
index 0000000..fd1e661
--- /dev/null
+++ b/tinyDSHOW/src/DSDisplayOverlay.VMR9.cxx
@@ -0,0 +1,211 @@
+/*
+* Copyright (C) 2009-2010 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(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/tinyDSHOW/src/DSDisplayOverlay.cxx b/tinyDSHOW/src/DSDisplayOverlay.cxx
new file mode 100644
index 0000000..e9a2e10
--- /dev/null
+++ b/tinyDSHOW/src/DSDisplayOverlay.cxx
@@ -0,0 +1,71 @@
+/*
+* Copyright (C) 2009-2010 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) && !defined(VMR9) && !defined(VMR9_WINDOWLESS)
+
+#include <tinydshow/DSDisplayOverlay.h>
+#include <tinydshow/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/tinyDSHOW/src/DSFrameRateFilter.cxx b/tinyDSHOW/src/DSFrameRateFilter.cxx
new file mode 100644
index 0000000..ba474ae
--- /dev/null
+++ b/tinyDSHOW/src/DSFrameRateFilter.cxx
@@ -0,0 +1,126 @@
+/*
+* Copyright (C) 2009-2010 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 <tinydshow/DSFrameRateFilter.h>
+
+#include <iostream>
+#include <string>
+
+using namespace std;
+
+#define FPS_INPUT 30
+#define FPS_OUTPUT 5
+
+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/tinyDSHOW/src/DSGrabber.cxx b/tinyDSHOW/src/DSGrabber.cxx
new file mode 100644
index 0000000..be87868
--- /dev/null
+++ b/tinyDSHOW/src/DSGrabber.cxx
@@ -0,0 +1,255 @@
+/*
+* Copyright (C) 2009-2010 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 <tinydshow/DSGrabber.h>
+#include <tinydshow/DSDisplay.h>
+#include <tinydshow/DSUtils.h>
+#include <tinydshow/DSCaptureUtils.h>
+#include <tinydshow/Resizer.h>
+
+#include <tinydshow/DSUtils.h>
+
+#include "tsk_debug.h"
+
+using namespace std;
+
+DSGrabber::DSGrabber(HRESULT *hr)
+: mutex_buffer(NULL), preview(NULL)
+{
+#ifdef _WIN32_WCE
+ this->graph = new DSCaptureGraph(this, hr);
+#else
+ this->graph = new DSCaptureGraph(this, hr);
+ if(!FAILED(*hr)){
+ this->preview = new DSDisplay(hr);
+ }
+#endif
+ if (FAILED(*hr)){
+ TSK_DEBUG_ERROR("Failed to create Grabber");
+ return;
+ }
+
+ // Init the bitmap info header with default values
+ memset(&(this->bitmapInfo), 0, sizeof(BITMAPINFOHEADER));
+ this->bitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
+ this->bitmapInfo.biWidth = 176;
+ this->bitmapInfo.biHeight = 144;
+ 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();
+}
+
+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->isRunning()){
+ first_buffer = true;
+
+ this->preview->start();
+ this->graph->connect();
+ this->graph->start();
+ }
+}
+void DSGrabber::stop()
+{
+ if (this->graph->isRunning()){
+ this->preview->stop();
+ this->graph->stop();
+ this->graph->disconnect();
+ }
+}
+
+bool DSGrabber::setCaptureParameters(int format, int f)
+{
+ tsk_mutex_lock(this->mutex_buffer);
+
+ // Get size from the format
+ VIDEOFORMAT_TO_SIZE(format, this->width, this->height)
+
+ // Store the framerate
+ this->fps = f;
+
+ // 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
+ this->preview->setFps(this->fps);
+ this->preview->setSize(this->width, this->height);
+
+ tsk_mutex_unlock(this->mutex_buffer);
+
+ return SUCCEEDED(hr);
+}
+
+VIDEOFORMAT DSGrabber::getCaptureFormat()
+{
+ VIDEOFORMAT format;
+ SIZE_TO_VIDEOFORMAT(this->width, this->height, format);
+ return format;
+}
+
+int DSGrabber::getFramerate()
+{
+ return this->fps;
+}
+
+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/tinyDSHOW/src/DSOutputFilter.cxx b/tinyDSHOW/src/DSOutputFilter.cxx
new file mode 100644
index 0000000..97f5182
--- /dev/null
+++ b/tinyDSHOW/src/DSOutputFilter.cxx
@@ -0,0 +1,113 @@
+/*
+* Copyright (C) 2009-2010 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 <tinydshow/DSOutputFilter.h>
+#include <tinydshow/DSOutputStream.h>
+#include <tinydshow/DSUtils.h>
+
+#include "tsk_memory.h"
+
+DSOutputFilter::DSOutputFilter(LPUNKNOWN pUnk, HRESULT *phr)
+: CSource(_T("TDSHOW_OUTPUT"), pUnk, CLSID_TdshowOutputFilter)
+{
+ CAutoLock cAutoLock(&m_cStateLock);
+
+ // 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/tinyDSHOW/src/DSOutputStream.cxx b/tinyDSHOW/src/DSOutputStream.cxx
new file mode 100644
index 0000000..dfc1393
--- /dev/null
+++ b/tinyDSHOW/src/DSOutputStream.cxx
@@ -0,0 +1,308 @@
+/*
+* Copyright (C) 2009-2010 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 <tinydshow/DSOutputStream.h>
+#include <tinydshow/DSOutputFilter.h>
+#include <tinydshow/DSUtils.h>
+
+#include <iostream>
+
+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)
+{
+//#ifndef _WIN32_WCE
+ 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 = 176;
+ this->height = 144;
+
+ this->overlay = false;
+
+ this->paintBuffer = NULL;
+ this->paintDC = NULL;
+ this->hDibSection = NULL;
+ this->hObject = NULL;
+
+ this->mutex = tsk_mutex_create();
+}
+
+DSOutputStream::~DSOutputStream()
+{
+ SAFE_DELETE_PTR(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;
+
+ CAutoLock lock(m_pFilter->pStateLock());
+
+ 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);
+
+ CAutoLock cAutoLock(m_pFilter->pStateLock());
+ 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, _tcslen( OVERLAY_TEXT ) ) ) return E_FAIL;
+#endif
+
+ CopyMemory(pBuffer, paintBuffer, lSize);
+
+ return S_OK;
+}
+
+/*inline*/ void DSOutputStream::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);
+ CAutoLock lock(m_pFilter->pStateLock());
+
+ HRESULT hr;
+ BYTE *pBuffer = NULL;
+ long lSize;
+
+ hr = pSample->GetPointer(&pBuffer);
+ if (SUCCEEDED(hr))
+ {
+ 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();
+ this->TransfertBuffer(this->buffer, (void*)pBuffer, TSK_MIN(lSize, this->buffer_size));
+ this->unlockBuffer();
+ }
+ else
+ {
+ // Avoid catching 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(lSize);
+ pSample->SetPreroll(FALSE);
+ pSample->SetDiscontinuity(FALSE);
+ }
+
+ // Set TRUE on every sample for uncompressed frames (KEYFRAME)
+ pSample->SetSyncPoint(TRUE);
+
+ return S_OK;
+}
diff --git a/tinyDSHOW/src/DSUtils.cxx b/tinyDSHOW/src/DSUtils.cxx
new file mode 100644
index 0000000..736984b
--- /dev/null
+++ b/tinyDSHOW/src/DSUtils.cxx
@@ -0,0 +1,155 @@
+/*
+* Copyright (C) 2009-2010 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 <tinydshow/DSUtils.h>
+
+#include <atlbase.h>
+#include <atlstr.h>
+
+bool IsMainThread()
+{
+ HWND hWnd = GetActiveWindow();
+ if(!hWnd) hWnd = GetForegroundWindow();
+ if(!hWnd) hWnd = GetConsoleWindow();
+
+ if(hWnd){
+ DWORD mainTid = GetWindowThreadProcessId(hWnd, NULL);
+ DWORD currentTid = GetCurrentThreadId();
+ return (mainTid == currentTid);
+ }
+ return false;
+}
+
+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)
+{
+ CComPtr<IEnumFilters> filterEnum = NULL;
+ CComPtr<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 = DisconnectFilters(graphBuilder, currentFilter, currentFilter);
+ }
+
+ filterEnum.Release();
+ return true;
+}
+
+bool RemoveAllFilters(IGraphBuilder *graphBuilder)
+{
+ CComPtr<IEnumFilters> filterEnum = NULL;
+ CComPtr<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)){
+ filterEnum.Release();
+ return false;
+ }
+ currentFilter.Release();
+ filterEnum->Reset();
+ }
+
+ filterEnum.Release();
+ return true;
+}
diff --git a/tinyDSHOW/src/Resizer.cxx b/tinyDSHOW/src/Resizer.cxx
new file mode 100644
index 0000000..2604c42
--- /dev/null
+++ b/tinyDSHOW/src/Resizer.cxx
@@ -0,0 +1,1097 @@
+/*
+* Copyright (C) 2009-2010 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.
+*
+*/
+/*
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ */
+#include <tinydshow/Resizer.h>
+
+//
+// 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/tinyDSHOW/src/VideoDisplayName.cxx b/tinyDSHOW/src/VideoDisplayName.cxx
new file mode 100644
index 0000000..a97f9e1
--- /dev/null
+++ b/tinyDSHOW/src/VideoDisplayName.cxx
@@ -0,0 +1,41 @@
+/*
+* Copyright (C) 2009-2010 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 "tinydshow/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/tinyDSHOW/src/VideoGrabberName.cxx b/tinyDSHOW/src/VideoGrabberName.cxx
new file mode 100644
index 0000000..a0c151c
--- /dev/null
+++ b/tinyDSHOW/src/VideoGrabberName.cxx
@@ -0,0 +1,41 @@
+/*
+* Copyright (C) 2009-2010 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 "tinydshow/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/tinyDSHOW/src/plugin/DSConsumer.cxx b/tinyDSHOW/src/plugin/DSConsumer.cxx
new file mode 100644
index 0000000..d525af6
--- /dev/null
+++ b/tinyDSHOW/src/plugin/DSConsumer.cxx
@@ -0,0 +1,278 @@
+/*
+* Copyright (C) 2009-2010 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 "tinydshow/plugin/DSConsumer.h"
+
+#include <tinydshow/DSDisplay.h>
+#include <tinydshow/DSUtils.h>
+
+#include "tsk_debug.h"
+
+
+#define DSCONSUMER(self) ((tdshow_consumer_t*)(self))
+
+typedef struct tdshow_consumer_s
+{
+ TMEDIA_DECLARE_CONSUMER;
+
+ DSDisplay* display;
+ INT64 window;
+
+ tsk_bool_t started;
+}
+tdshow_consumer_t;
+
+
+
+/* ============ Media Producer Interface ================= */
+int tdshow_consumer_set(tmedia_consumer_t *self, const tmedia_param_t* param)
+{
+ int ret = 0;
+
+ if(!self || !param){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(param->value_type == tmedia_pvt_int64){
+ if(tsk_striequals(param->key, "remote-hwnd")){
+ INT64 hWnd = (INT64)*((int64_t*)param->value);
+ if(DSCONSUMER(self)->display){
+ if(hWnd){
+ DSCONSUMER(self)->display->attach(hWnd);
+ }
+ else{
+ DSCONSUMER(self)->display->detach();
+ }
+ }
+ else{
+ DSCONSUMER(self)->window = hWnd;
+ }
+ }
+ }
+
+ return ret;
+}
+
+
+int tdshow_consumer_prepare(tmedia_consumer_t* self, const tmedia_codec_t* codec)
+{
+ tdshow_consumer_t* consumer = (tdshow_consumer_t*)self;
+
+ if(!consumer || !codec && codec->plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ TMEDIA_CONSUMER(consumer)->video.fps = TMEDIA_CODEC_VIDEO(codec)->fps;
+ TMEDIA_CONSUMER(consumer)->video.in.width = TMEDIA_CODEC_VIDEO(codec)->width;
+ TMEDIA_CONSUMER(consumer)->video.in.height = TMEDIA_CODEC_VIDEO(codec)->height;
+
+ if(!TMEDIA_CONSUMER(consumer)->video.display.width){
+ TMEDIA_CONSUMER(consumer)->video.display.width = TMEDIA_CONSUMER(consumer)->video.in.width;
+ }
+ if(!TMEDIA_CONSUMER(consumer)->video.display.height){
+ TMEDIA_CONSUMER(consumer)->video.display.height = TMEDIA_CONSUMER(consumer)->video.in.height;
+ }
+
+ return 0;
+}
+
+int tdshow_consumer_start(tmedia_consumer_t* self)
+{
+ tdshow_consumer_t* consumer = (tdshow_consumer_t*)self;
+ HRESULT hr;
+
+ if(!consumer){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(consumer->started){
+ TSK_DEBUG_WARN("Producer already started");
+ return 0;
+ }
+
+ if(!consumer->display){ /* Last chance to create the display */
+ if(!IsMainThread()){
+ TSK_DEBUG_WARN("Creating DirectShow objects outside the MainThread");
+ }
+ // create display
+ consumer->display = new DSDisplay(&hr);
+ if(FAILED(hr)){
+ TSK_DEBUG_ERROR("Failed to created DirectShow Display");
+ SAFE_DELETE_PTR(consumer->display);
+ return -2;
+ }
+ }
+ // Set parameters
+ consumer->display->setFps(TMEDIA_CONSUMER(consumer)->video.fps);
+ // do not change the display size: see hook()
+ // consumer->display->setSize(TMEDIA_CONSUMER(consumer)->video.display.width, TMEDIA_CONSUMER(consumer)->video.display.height);
+ if(consumer->window){
+ consumer->display->attach(consumer->window);
+ }
+
+ // Start display
+ TSK_DEBUG_INFO("Before starting DirectShow consumer");
+ consumer->display->start();
+ consumer->started = tsk_true;
+ TSK_DEBUG_INFO("After starting DirectShow consumer");
+
+ return 0;
+}
+
+int tdshow_consumer_consume(tmedia_consumer_t* self, void** buffer, tsk_size_t size, const tsk_object_t* proto_hdr)
+{
+ tdshow_consumer_t* consumer = (tdshow_consumer_t*)self;
+ if(consumer && consumer->display && buffer){
+ consumer->display->handleVideoFrame(*buffer, TMEDIA_CONSUMER(consumer)->video.display.width, TMEDIA_CONSUMER(consumer)->video.display.height);
+ return 0;
+ }
+ else{
+ TSK_DEBUG_ERROR("Invlide parameter");
+ return -1;
+ }
+}
+
+int tdshow_consumer_pause(tmedia_consumer_t* self)
+{
+ tdshow_consumer_t* consumer = (tdshow_consumer_t*)self;
+
+ if(!consumer){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(!consumer->display){
+ TSK_DEBUG_ERROR("Invalid internal grabber");
+ return -2;
+ }
+
+ //consumer->display->pause();
+
+ return 0;
+}
+
+int tdshow_consumer_stop(tmedia_consumer_t* self)
+{
+ tdshow_consumer_t* consumer = (tdshow_consumer_t*)self;
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(!consumer->started){
+ TSK_DEBUG_WARN("Consumer not started");
+ return 0;
+ }
+
+ if(!consumer->display){
+ TSK_DEBUG_ERROR("Invalid internal display");
+ return -2;
+ }
+
+ TSK_DEBUG_INFO("Before stopping DirectShow consumer");
+ consumer->display->stop();
+ consumer->started = tsk_false;
+ TSK_DEBUG_INFO("After stopping DirectShow consumer");
+
+ return 0;
+}
+
+
+//
+// WaveAPI consumer object definition
+//
+/* constructor */
+static tsk_object_t* tdshow_consumer_ctor(tsk_object_t * self, va_list * app)
+{
+ CoInitialize(NULL);
+
+ tdshow_consumer_t *consumer = (tdshow_consumer_t *)self;
+ if(consumer){
+ HRESULT hr;
+
+ /* init base */
+ tmedia_consumer_init(TMEDIA_CONSUMER(consumer));
+ TMEDIA_CONSUMER(consumer)->video.display.chroma = tmedia_bgr24; // RGB24 on x86 (little endians) stored as BGR24
+
+ /* init self */
+ TMEDIA_CONSUMER(consumer)->video.fps = 15;
+ TMEDIA_CONSUMER(consumer)->video.display.width = 352;
+ TMEDIA_CONSUMER(consumer)->video.display.height = 288;
+ TMEDIA_CONSUMER(consumer)->video.display.auto_resize = tsk_true;
+
+ if(IsMainThread()){
+ consumer->display = new DSDisplay(&hr);
+ if(FAILED(hr)){
+ TSK_DEBUG_ERROR("Failed to created DirectShow Display");
+ SAFE_DELETE_PTR(consumer->display);
+ }
+ }
+ }
+ return self;
+}
+/* destructor */
+static tsk_object_t* tdshow_consumer_dtor(tsk_object_t * self)
+{
+ tdshow_consumer_t *consumer = (tdshow_consumer_t *)self;
+ if(consumer){
+
+ /* stop */
+ if(consumer->started){
+ tdshow_consumer_stop((tmedia_consumer_t*)self);
+ }
+
+ /* deinit base */
+ tmedia_consumer_deinit(TMEDIA_CONSUMER(consumer));
+ /* deinit self */
+ SAFE_DELETE_PTR(consumer->display);
+
+ }
+
+ return self;
+}
+/* object definition */
+static const tsk_object_def_t tdshow_consumer_def_s =
+{
+ sizeof(tdshow_consumer_t),
+ tdshow_consumer_ctor,
+ tdshow_consumer_dtor,
+ tsk_null,
+};
+/* plugin definition*/
+static const tmedia_consumer_plugin_def_t tdshow_consumer_plugin_def_s =
+{
+ &tdshow_consumer_def_s,
+
+ tmedia_video,
+ "Microsoft DirectShow consumer",
+
+ tdshow_consumer_set,
+ tdshow_consumer_prepare,
+ tdshow_consumer_start,
+ tdshow_consumer_consume,
+ tdshow_consumer_pause,
+ tdshow_consumer_stop
+};
+extern const tmedia_consumer_plugin_def_t *tdshow_consumer_plugin_def_t = &tdshow_consumer_plugin_def_s;
diff --git a/tinyDSHOW/src/plugin/DSProducer.cxx b/tinyDSHOW/src/plugin/DSProducer.cxx
new file mode 100644
index 0000000..52b110f
--- /dev/null
+++ b/tinyDSHOW/src/plugin/DSProducer.cxx
@@ -0,0 +1,278 @@
+/*
+* Copyright (C) 2009-2010 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 "tinydshow/plugin/DSProducer.h"
+
+#include <tinydshow/DSGrabber.h>
+#include <tinydshow/DSDisplay.h>
+#include <tinydshow/DSUtils.h>
+
+#include "tsk_debug.h"
+
+
+#define DSPRODUCER(self) ((tdshow_producer_t*)(self))
+
+typedef struct tdshow_producer_s
+{
+ TMEDIA_DECLARE_PRODUCER;
+
+ DSGrabber* grabber;
+ INT64 previewHwnd;
+
+ int fps;
+ int width;
+ int height;
+
+ tsk_bool_t started;
+}
+tdshow_producer_t;
+
+// Producer callback (From DirectShow Grabber to our plugin)
+static int tdshow_plugin_cb(const void* callback_data, const void* buffer, tsk_size_t size)
+{
+ const tdshow_producer_t* producer = (const tdshow_producer_t*)callback_data;
+
+ if(producer && TMEDIA_PRODUCER(producer)->enc_cb.callback){
+ TMEDIA_PRODUCER(producer)->enc_cb.callback(TMEDIA_PRODUCER(producer)->enc_cb.callback_data, buffer, size);
+ }
+
+ return 0;
+}
+
+
+/* ============ Media Producer Interface ================= */
+int tdshow_producer_set(tmedia_producer_t *self, const tmedia_param_t* param)
+{
+ int ret = 0;
+
+ if(!self || !param){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(param->value_type == tmedia_pvt_int64){
+ if(tsk_striequals(param->key, "local-hwnd")){
+ if(DSPRODUCER(self)->grabber && DSPRODUCER(self)->grabber->preview){
+ DSPRODUCER(self)->grabber->preview->attach((INT64)*((int64_t*)param->value));
+ }
+ else{
+ DSPRODUCER(self)->previewHwnd = (INT64)*((int64_t*)param->value);
+ }
+ }
+ }
+
+ return ret;
+}
+
+int tdshow_producer_prepare(tmedia_producer_t* self, const tmedia_codec_t* codec)
+{
+ tdshow_producer_t* producer = (tdshow_producer_t*)self;
+
+ if(!producer || !codec && codec->plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ producer->fps = TMEDIA_CODEC_VIDEO(codec)->fps;
+ producer->width = TMEDIA_CODEC_VIDEO(codec)->width;
+ producer->height = TMEDIA_CODEC_VIDEO(codec)->height;
+
+ return 0;
+}
+
+int tdshow_producer_start(tmedia_producer_t* self)
+{
+ tdshow_producer_t* producer = (tdshow_producer_t*)self;
+ VIDEOFORMAT format;
+ HRESULT hr;
+
+ if(!producer){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(producer->started){
+ TSK_DEBUG_WARN("Producer already started");
+ return 0;
+ }
+
+ if(!producer->grabber){ /* Last chance to greate the graber */
+ if(!IsMainThread()){
+ TSK_DEBUG_WARN("Creating DirectShow objects outside the MainThread");
+ }
+ producer->grabber = new DSGrabber(&hr);
+ if(FAILED(hr)){
+ TSK_DEBUG_ERROR("Failed to created DirectShow Grabber");
+ SAFE_DELETE_PTR(producer->grabber);
+ return -2;
+ }
+ }
+
+ //set Source device
+ producer->grabber->setCaptureDevice("Null");
+
+ // set parameters
+ SIZE_TO_VIDEOFORMAT(producer->width, producer->height, format);
+ producer->grabber->setCaptureParameters(format, producer->fps);
+
+ // set callback function
+ producer->grabber->setCallback(tdshow_plugin_cb, producer);
+
+ // attach preview
+ if(producer->grabber->preview){
+ if(producer->previewHwnd){
+ producer->grabber->preview->attach(producer->previewHwnd);
+ }
+ producer->grabber->preview->setSize(producer->width, producer->height);
+ }
+
+ // start grabber
+ TSK_DEBUG_INFO("Before starting DirectShow producer");
+ producer->grabber->start();
+ producer->started = tsk_true;
+ TSK_DEBUG_INFO("After starting DirectShow producer");
+
+ return 0;
+}
+
+int tdshow_producer_pause(tmedia_producer_t* self)
+{
+ tdshow_producer_t* producer = (tdshow_producer_t*)self;
+
+ if(!producer){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(!producer->grabber){
+ TSK_DEBUG_ERROR("Invalid internal grabber");
+ return -2;
+ }
+
+ //producer->grabber->pause();
+
+ return 0;
+}
+
+int tdshow_producer_stop(tmedia_producer_t* self)
+{
+ tdshow_producer_t* producer = (tdshow_producer_t*)self;
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(!producer->started){
+ TSK_DEBUG_WARN("Producer not started");
+ return 0;
+ }
+
+ if(!producer->grabber){
+ TSK_DEBUG_ERROR("Invalid internal grabber");
+ return -2;
+ }
+
+ producer->grabber->stop();
+ producer->started = tsk_false;
+
+ return 0;
+}
+
+
+//
+// WaveAPI producer object definition
+//
+/* constructor */
+static tsk_object_t* tdshow_producer_ctor(tsk_object_t * self, va_list * app)
+{
+ CoInitialize(NULL);
+
+ tdshow_producer_t *producer = (tdshow_producer_t *)self;
+ if(producer){
+ HRESULT hr;
+
+ /* init base */
+ tmedia_producer_init(TMEDIA_PRODUCER(producer));
+ TMEDIA_PRODUCER(producer)->video.chroma = tmedia_bgr24; // RGB24 on x86 (little endians) stored as BGR24
+ /* init self with default values*/
+ producer->fps = 15;
+ producer->width = 176;
+ producer->height = 144;
+
+ if(IsMainThread()){
+ producer->grabber = new DSGrabber(&hr);
+ if(FAILED(hr)){
+ TSK_DEBUG_ERROR("Failed to created DirectShow Grabber");
+ SAFE_DELETE_PTR(producer->grabber);
+ }
+ }
+ }
+ return self;
+}
+/* destructor */
+static tsk_object_t* tdshow_producer_dtor(tsk_object_t * self)
+{
+ tdshow_producer_t *producer = (tdshow_producer_t *)self;
+ if(producer){
+
+ /* stop */
+ if(producer->started){
+ tdshow_producer_stop((tmedia_producer_t*)self);
+ }
+
+ /* for safety */
+ if(producer->grabber){
+ producer->grabber->setCallback(tsk_null, tsk_null);
+ }
+
+ /* deinit base */
+ tmedia_producer_deinit(TMEDIA_PRODUCER(producer));
+ /* deinit self */
+ SAFE_DELETE_PTR(producer->grabber);
+
+ }
+
+ return self;
+}
+/* object definition */
+static const tsk_object_def_t tdshow_producer_def_s =
+{
+ sizeof(tdshow_producer_t),
+ tdshow_producer_ctor,
+ tdshow_producer_dtor,
+ tsk_null,
+};
+/* plugin definition*/
+static const tmedia_producer_plugin_def_t tdshow_producer_plugin_def_s =
+{
+ &tdshow_producer_def_s,
+
+ tmedia_video,
+ "Microsoft DirectShow producer",
+
+ tdshow_producer_set,
+ tdshow_producer_prepare,
+ tdshow_producer_start,
+ tdshow_producer_pause,
+ tdshow_producer_stop
+};
+extern const tmedia_producer_plugin_def_t *tdshow_producer_plugin_def_t = &tdshow_producer_plugin_def_s;
diff --git a/tinyDSHOW/tinyDSHOW.vcproj b/tinyDSHOW/tinyDSHOW.vcproj
new file mode 100644
index 0000000..5f49ed2
--- /dev/null
+++ b/tinyDSHOW/tinyDSHOW.vcproj
@@ -0,0 +1,348 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="tinyDSHOW"
+ ProjectGUID="{0CCC02F1-4233-424F-AD5E-A021456E6E8D}"
+ RootNamespace="tinyDSHOW"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\thirdparties\win32\include;&quot;$(PSDK_DIR)include&quot;;&quot;$(DXSDK_DIR)include&quot;;..\thirdparties\win32\include\directshow;include;..\tinySAK\src;..\tinyMEDIA\include;..\tinySDP\include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;TINYDSHOW_EXPORTS;_WIN32_WINNT=0x0501"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ WarnAsError="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="..\thirdparties\win32\lib\directshow\strmbasd.lib dmoguids.lib strmiids.lib uuid.lib Winmm.lib $(OutDir)\tinySAK.lib $(OutDir)\tinyMEDIA.lib"
+ LinkIncremental="2"
+ IgnoreDefaultLibraryNames="oldnames.lib;LIBCMT.lib"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="false"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="..\thirdparties\win32\include;&quot;$(PSDK_DIR)include&quot;;&quot;$(DXSDK_DIR)include&quot;;..\thirdparties\win32\include\directshow;include;..\tinySAK\src;..\tinyMEDIA\include;..\tinySDP\include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_WIN32_WINNT=0x0501;TINYDSHOW_EXPORTS"
+ BasicRuntimeChecks="0"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ WarnAsError="true"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="..\thirdparties\win32\lib\directshow\strmbase.lib dmoguids.lib strmiids.lib uuid.lib Winmm.lib $(OutDir)\tinySAK.lib $(OutDir)\tinyMEDIA.lib"
+ LinkIncremental="1"
+ IgnoreDefaultLibraryNames=""
+ GenerateDebugInformation="false"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="0"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="headers(*.h)"
+ >
+ <File
+ RelativePath=".\include\tinydshow\DSBufferWriter.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinydshow\DSCaptureFormat.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinydshow\DSCaptureGraph.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinydshow\DSCaptureUtils.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinydshow\DSDisplay.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinydshow\DSDisplayGraph.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinydshow\DSDisplayOverlay.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinydshow\DSFrameRateFilter.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinydshow\DSGrabber.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinydshow\DSOutputFilter.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinydshow\DSOutputStream.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinydshow\DSUtils.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinydshow\Resizer.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinydshow_config.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinydshow\VideoDisplayName.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinydshow\VideoFrame.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinydshow\VideoGrabberName.h"
+ >
+ </File>
+ <Filter
+ Name="plugin"
+ >
+ <File
+ RelativePath=".\include\tinydshow\plugin\DSConsumer.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinydshow\plugin\DSProducer.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="source(*cxx)"
+ >
+ <File
+ RelativePath=".\src\DSCaptureFormat.cxx"
+ >
+ </File>
+ <File
+ RelativePath=".\src\DSCaptureGraph.cxx"
+ >
+ </File>
+ <File
+ RelativePath=".\src\DSCaptureUtils.cxx"
+ >
+ </File>
+ <File
+ RelativePath=".\src\DSDisplay.cxx"
+ >
+ </File>
+ <File
+ RelativePath=".\src\DSDisplayGraph.cxx"
+ >
+ </File>
+ <File
+ RelativePath=".\src\DSDisplayOverlay.cxx"
+ >
+ </File>
+ <File
+ RelativePath=".\src\DSDisplayOverlay.VMR.cxx"
+ >
+ </File>
+ <File
+ RelativePath=".\src\DSDisplayOverlay.VMR9.cxx"
+ >
+ </File>
+ <File
+ RelativePath=".\src\DSFrameRateFilter.cxx"
+ >
+ </File>
+ <File
+ RelativePath=".\src\DSGrabber.cxx"
+ >
+ </File>
+ <File
+ RelativePath=".\src\DSOutputFilter.cxx"
+ >
+ </File>
+ <File
+ RelativePath=".\src\DSOutputStream.cxx"
+ >
+ </File>
+ <File
+ RelativePath=".\src\DSUtils.cxx"
+ >
+ </File>
+ <File
+ RelativePath=".\src\Resizer.cxx"
+ >
+ </File>
+ <File
+ RelativePath=".\src\VideoDisplayName.cxx"
+ >
+ </File>
+ <File
+ RelativePath=".\src\VideoGrabberName.cxx"
+ >
+ </File>
+ <Filter
+ Name="plugin"
+ >
+ <File
+ RelativePath=".\src\plugin\DSConsumer.cxx"
+ >
+ </File>
+ <File
+ RelativePath=".\src\plugin\DSProducer.cxx"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
OpenPOWER on IntegriCloud