Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

From Cedric Pinson, "Here an update of the directshow plugin. It fixe…

…s issues with

synchronization, improve capture device support.

here how to use it to display a capture device:

osg::Options* options = new osg::Options;
options->setPluginStringData("captureWantedWidth", "800");
options->setPluginStringData("captureWantedHeight", "600");
options->setPluginStringData("captureWantedFps", "30");
options->setPluginStringData("captureVideoDevice", "USB Video Device" );
options->setPluginStringData("captureSoundDevice", "");
then
osgDB::readImageFile("capture.directshow", options)
you can use a graphedit application to list devices available in
directshow.


for classic avi file you just need to do a
osgDB::readImageFile("file.avi.directshow");
You will need of course to install the codec needed by directshow to
read the avi files.

I recommand this tool http://avicodec.duby.info/, that check which
video/sound codec is needed to play an avi file.


You can test it with the osgmovie example.
"
  • Loading branch information...
commit d77c4a1ee768fc2df94ce2cbb78aabdd533941d9 1 parent c253fef
Robert OSFIELD authored
View
1  CMakeLists.txt
@@ -363,6 +363,7 @@ FIND_PACKAGE(OurDCMTK)
FIND_PACKAGE(OpenAL)
FIND_PACKAGE(XUL)
FIND_PACKAGE(FFmpeg)
+FIND_PACKAGE(DirectShow)
FIND_PACKAGE(SDL)
#use pkg-config to find various modues
View
58 CMakeModules/FindDirectShow.cmake
@@ -0,0 +1,58 @@
+# Locate directshow
+# This module defines
+# DIRECTSHOW_LIBRARIES
+# DIRECTSHOW_FOUND, if false, do not try to link to directshow
+# DIRECTSHOW_INCLUDE_DIR, where to find the headers
+#
+# $DIRECTSHOW_DIR is an environment variable that would
+# point to the this path in the plateform devkit (Samples\Multimedia\DirectShow)
+#
+# Created by Cedric Pinson.
+#
+
+
+SET(DIRECTSHOW_FOUND "NO")
+SET(DIRECTSHOW_SAMPLE_ROOT "$ENV{DIRECTSHOW_DIR}" CACHE PATH "Location of DirectShow sample in devkit")
+
+IF(WIN32)
+ FIND_PATH(DIRECTSHOW_STRMBASE_INCLUDE_DIRS renbase.h
+ PATHS
+ ${DIRECTSHOW_SAMPLE_ROOT}/BaseClasses/
+ $ENV{DIRECTSHOW_SAMPLE_ROOT}/BaseClasses/
+ DOC "Location of DirectShow Base include on the windows devkit"
+ )
+
+ FIND_LIBRARY(DIRECTSHOW_STRMBASE_LIBRARY_RELEASE strmbase
+ PATHS
+ ${DIRECTSHOW_SAMPLE_ROOT}/BaseClasses/Release_MBCS/ # sdk 6.1
+ $ENV{DIRECTSHOW_SAMPLE_ROOT}/BaseClasses/Release_MBCS/ # sdk 6.1
+ ${DIRECTSHOW_SAMPLE_ROOT}/BaseClasses/Release/ # sdk 2003
+ $ENV{DIRECTSHOW_SAMPLE_ROOT}/BaseClasses/Release/ # sdk 2003
+ DOC "Location of DirectShow Base library on the windows devkit"
+ )
+
+ FIND_LIBRARY(DIRECTSHOW_STRMBASE_LIBRARY_DEBUG strmbasd
+ PATHS
+ ${DIRECTSHOW_SAMPLE_ROOT}/BaseClasses/Debug_MBCS/ # sdk 6.1
+ $ENV{DIRECTSHOW_SAMPLE_ROOT}/BaseClasses/Debug_MBCS/ # sdk 6.1
+ ${DIRECTSHOW_SAMPLE_ROOT}/BaseClasses/Debug/ # sdk 2003
+ $ENV{DIRECTSHOW_SAMPLE_ROOT}/BaseClasses/Debug/ # sdk 2003
+ DOC "Location of DirectShow Base library on the windows devkit"
+ )
+
+ IF (DIRECTSHOW_STRMBASE_INCLUDE_DIRS AND DIRECTSHOW_STRMBASE_LIBRARY_RELEASE)
+ SET(WIN_LIBS winmm d3d9 d3dx9 kernel32 user32 gdi32 winspool shell32 ole32 oleaut32 uuid comdlg32 advapi32)
+ SET(DIRECTSHOW_FOUND "YES")
+ SET(DIRECTSHOW_LIBRARY_DEBUG
+ ${DIRECTSHOW_STRMBASE_LIBRARY_DEBUG}
+ )
+ SET(DIRECTSHOW_LIBRARY
+ ${DIRECTSHOW_STRMBASE_LIBRARY_RELEASE}
+ )
+ SET(DIRECTSHOW_INLUDE_DIRS
+ ${DIRECTSHOW_STRMBASE_INCLUDE_DIRS}
+ )
+
+ ENDIF()
+
+ENDIF()
View
4 src/osgPlugins/CMakeLists.txt
@@ -208,6 +208,10 @@ IF(FFMPEG_FOUND)
ADD_SUBDIRECTORY(ffmpeg)
ENDIF()
+IF(DIRECTSHOW_FOUND)
+ ADD_SUBDIRECTORY(directshow)
+ENDIF()
+
# IF(OPENAL_FOUND)
# ADD_SUBDIRECTORY(OpenAL)
# ENDIF()
View
68 src/osgPlugins/directshow/CMakeLists.txt
@@ -0,0 +1,68 @@
+# For visual studio express 2005 and windows plateforme sdk 2003
+# i have some problem with the windows sdk to build the BaseClasses, so
+# here some point that will help to fix this.
+# https://blogs.msdn.com/mikewasson/archive/2005/05/23/421116.aspx
+
+# use this link to downloads vc project to build strmbase library
+# http://www.microsoft.com/downloads/thankyou.aspx?familyId=8af0afa9-1383-44b4-bc8b-7d6315212323&displayLang=en
+
+# to build strmbase.lib
+# modify clutil.h line 278
+# operator=(LONG);
+# to
+# (LONG) operator=(LONG);
+
+# add in includes directory
+# C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include\atl
+
+# modify winutil.cpp line 2104
+# for (Count = 0;Count < Result;Count++) {
+# to
+# for (UINT Count = 0;Count < Result;Count++) {
+
+# modify winutil.cpp line 2123
+# for (Count = PalLoCount;INT(Count) < min(PalHiStart,iColours);Count++) {
+# to
+# for (UINT Count = PalLoCount;INT(Count) < min(PalHiStart,iColours);Count++) {
+
+# modify wxdebug.cpp line 564
+# static g_dwLastRefresh = 0;
+# to
+# static DWORD g_dwLastRefresh = 0;
+
+# modify outputq.cpp line 6134
+# LONG iLost = 0;
+# for (long iDone = 0;
+# to
+# LONG iLost = 0;
+# long iDone = 0;
+# for (iDone = 0;
+
+# In the properties of the project there is a fixed path to link with strmiids.lib. Replace the ../../../.. by the name of the library
+# only, then the linker will find the strmiids.lib
+
+# After those step it should compile, becareful using unicode version will result undefined symbol ... so use multibyte version instead
+#
+# End For visual studio express 2005 and windows plateforme sdk 2003
+
+
+INCLUDE_DIRECTORIES( ${DIRECTSHOW_INLUDE_DIRS} )
+SET (TARGET_EXTERNAL_LIBRARIES
+ quartz comsuppw winmm d3d9 d3dx9 kernel32 user32 gdi32 winspool shell32 ole32 oleaut32 uuid comdlg32 advapi32
+ )
+
+SET(TARGET_SRC
+ ReaderWriterDirectShow.cpp
+ DirectShowTexture.cpp
+)
+
+SET(TARGET_H
+ DirectShowTexture
+)
+SET(TARGET_LIBRARIES_VARS DIRECTSHOW_LIBRARY )
+
+#### end var setup ###
+SETUP_PLUGIN(directshow directshow)
+SET_TARGET_PROPERTIES("${TARGET_DEFAULT_PREFIX}${TARGET_NAME}" PROPERTIES LINK_FLAGS "/NODEFAULTLIB:atlthunk")
+
+
View
125 src/osgPlugins/directshow/DirectShowTexture
@@ -0,0 +1,125 @@
+/* -*-c++-*- OpenSceneGraph - Copyright (C) 2009 Tharsis Software
+ *
+ * This library is open source and may be redistributed and/or modified under
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version. The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * This library 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
+ * OpenSceneGraph Public License for more details.
+ *
+ * Authors:
+ * Cedric Pinson <cedric.pinson@plopbyte.net>
+*/
+
+#ifndef DirectShowTexture
+#define DirectShowTexture 1
+
+#include <streams.h>
+#include <map>
+#include <osg/ImageStream>
+#include <osg/observer_ptr>
+#include <OpenThreads/Thread>
+#include <OpenThreads/Mutex>
+#include <OpenThreads/ScopedLock>
+
+//-----------------------------------------------------------------------------
+// Define GUID for Texture Renderer
+// {71771540-2017-11cf-AE26-0020AFD79767}
+//-----------------------------------------------------------------------------
+struct __declspec(uuid("{71771540-2017-11cf-ae26-0020afd79767}")) CLSID_TextureRenderer;
+
+class CTextureRenderer;
+
+class DirectShowImageStream : public osg::ImageStream
+{
+public:
+ typedef std::map<std::string,std::string> Options;
+
+protected:
+ osg::observer_ptr<CTextureRenderer> _renderer;
+ mutable OpenThreads::Mutex _mutex;
+ Options _options;
+
+public:
+ DirectShowImageStream();
+ ~DirectShowImageStream();
+ DirectShowImageStream(const DirectShowImageStream & image, const osg::CopyOp & copyop = osg::CopyOp::SHALLOW_COPY);
+
+ META_Object(osgDirectShow, DirectShowImageStream);
+ void run();
+ bool openFile(const std::string& file);
+ bool openCaptureDevices();
+ void setOptions(const Options& map);
+ void play();
+ void pause();
+ void rewind();
+ osg::ImageStream::StreamStatus getStatus();
+ void seek(double time);
+ double getLength() const;
+ double getFrameRate() const;
+ void setTimeMultiplier(double rate);
+ double getTimeMultiplier() const;
+ void quit(bool /*waitForThreadToExit*/ = true);
+ void stop();
+};
+
+
+//-----------------------------------------------------------------------------
+// CTextureRenderer Class Declarations
+//-----------------------------------------------------------------------------
+class CTextureRenderer : public CBaseVideoRenderer, public osg::Referenced
+{
+public:
+ IGraphBuilder* _graphBuilder; // GraphBuilder
+ IMediaControl* _mediaControl; // Media Control
+ IMediaSeeking* _mediaSeeking; // Media seeking
+ IMediaEvent* _mediaEvent; // Media Event
+ IBaseFilter* _videoCaptureDevice;
+ IBaseFilter* _fileSource;
+ IBaseFilter* _soundOutputDevice;
+ IBaseFilter* _soundCaptureDevice;
+ HRESULT _dropFrame;
+
+ CTextureRenderer(DirectShowImageStream* imageStream, HRESULT* valid);
+ ~CTextureRenderer();
+
+ void setFilename(const std::string& filename);
+ bool initBuildGraph();
+ bool initCaptureDevice();
+ bool openCaptureDevices(const DirectShowImageStream::Options& options);
+ bool openVideoCaptureDevice(const std::string& capture, int wantWidth, int wantHeight, double wantFps);
+ bool openSoundCaptureDevice(const std::string& capture, int nbChannels = 2);
+
+
+ bool openFile(const std::string& file);
+ bool startGraph();
+ void syncStreams(bool state);
+ bool setupOutputSoundDevice(ICreateDevEnum* devs);
+ void releaseRessources();
+ IGraphBuilder* getGraphBuilder() { return _graphBuilder; }
+
+ HRESULT ShouldDrawSampleNow(IMediaSample *sample, REFERENCE_TIME *start, REFERENCE_TIME *stop);
+ bool StopFilters();
+
+ HRESULT CheckMediaType(const CMediaType *pmt ); // Format acceptable?
+ HRESULT SetMediaType(const CMediaType *pmt ); // Video format notification
+ HRESULT DoRenderSample(IMediaSample *pMediaSample); // New video sample
+
+ int _width;
+ int _height;
+ int _pitch;
+ std::string _videoCaptureDeviceName;
+ std::string _soundCaptureDeviceName;
+ std::string _soundOutputDeviceName;
+ std::string _filename;
+ const std::string& getVideoCaptureDeviceName() const { return _videoCaptureDeviceName; }
+ const std::string& getSoundOutputDeviceName() const { return _soundOutputDeviceName; }
+ const std::string& getSoundCaptureDeviceName() const { return _soundCaptureDeviceName; }
+ const std::string& getFilename() const { return _filename; }
+ osg::observer_ptr<DirectShowImageStream> _imageStream;
+};
+
+#endif
View
1,872 src/osgPlugins/directshow/DirectShowTexture.cpp
@@ -0,0 +1,1872 @@
+/* -*-c++-*- OpenSceneGraph - Copyright (C) 2009 Tharsis Software
+ *
+ * This library is open source and may be redistributed and/or modified under
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version. The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * This library 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
+ * OpenSceneGraph Public License for more details.
+ *
+ * Authors:
+ * Cedric Pinson <cedric.pinson@plopbyte.net>
+*/
+
+#include "DirectShowTexture"
+#include <osg/notify>
+#include <osgDB/WriteFile>
+#include <sstream>
+#include <windows.h>
+#include <mmsystem.h>
+#include <comdef.h>
+
+#include <strsafe.h>
+#include <functional>
+#include <locale>
+#include <string>
+
+HRESULT GetPin(IBaseFilter* pFilter, LPCWSTR pName, IPin** ppPin);
+HRESULT GetPin(IBaseFilter* pFilter, const GUID* pFormat, PIN_DIRECTION PinDir, IPin** ppPin);
+
+
+struct NamedGuid
+{
+ const GUID *pguid;
+ const TCHAR *psz;
+};
+
+// 73646976-0000-0010-8000-00AA00389B71 'vids' == WMMEDIATYPE_Video
+EXTERN_GUID(WMMEDIATYPE_Video,
+0x73646976, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
+// 73647561-0000-0010-8000-00AA00389B71 'auds' == WMMEDIATYPE_Audio
+EXTERN_GUID(WMMEDIATYPE_Audio,
+0x73647561, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
+// 73636d64-0000-0010-8000-00AA00389B71 'scmd' == MEDIATYPE_Script
+EXTERN_GUID(WMMEDIATYPE_Script,
+0x73636d64, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
+// 34A50FD8-8AA5-4386-81FE-A0EFE0488E31 WMMEDIATYPE_Image
+EXTERN_GUID(WMMEDIATYPE_Image,
+0x34a50fd8, 0x8aa5, 0x4386, 0x81, 0xfe, 0xa0, 0xef, 0xe0, 0x48, 0x8e, 0x31);
+// D9E47579-930E-4427-ADFC-AD80F290E470 'fxfr' == WMMEDIATYPE_FileTransfer
+EXTERN_GUID(WMMEDIATYPE_FileTransfer,
+0xd9e47579, 0x930e, 0x4427, 0xad, 0xfc, 0xad, 0x80, 0xf2, 0x90, 0xe4, 0x70);
+// 9BBA1EA7-5AB2-4829-BA57-0940209BCF3E 'text' == WMMEDIATYPE_Text
+EXTERN_GUID(WMMEDIATYPE_Text,
+0x9bba1ea7, 0x5ab2, 0x4829, 0xba, 0x57, 0x9, 0x40, 0x20, 0x9b, 0xcf, 0x3e);
+
+// 00000000-0000-0010-8000-00AA00389B71 WMMEDIASUBTYPE_Base
+EXTERN_GUID(WMMEDIASUBTYPE_Base,
+0x00000000, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
+// e436eb78-524f-11ce-9f53-0020af0ba770 MEDIASUBTYPE_RGB1
+EXTERN_GUID(WMMEDIASUBTYPE_RGB1,
+0xe436eb78, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
+// e436eb79-524f-11ce-9f53-0020af0ba770 MEDIASUBTYPE_RGB4
+EXTERN_GUID(WMMEDIASUBTYPE_RGB4,
+0xe436eb79, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
+// e436eb7a-524f-11ce-9f53-0020af0ba770 MEDIASUBTYPE_RGB8
+EXTERN_GUID(WMMEDIASUBTYPE_RGB8,
+0xe436eb7a, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
+// e436eb7b-524f-11ce-9f53-0020af0ba770 MEDIASUBTYPE_RGB565
+EXTERN_GUID(WMMEDIASUBTYPE_RGB565,
+0xe436eb7b, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
+// e436eb7c-524f-11ce-9f53-0020af0ba770 MEDIASUBTYPE_RGB555
+EXTERN_GUID(WMMEDIASUBTYPE_RGB555,
+0xe436eb7c, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
+// e436eb7d-524f-11ce-9f53-0020af0ba770 MEDIASUBTYPE_RGB24
+EXTERN_GUID(WMMEDIASUBTYPE_RGB24,
+0xe436eb7d, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
+// e436eb7e-524f-11ce-9f53-0020af0ba770 MEDIASUBTYPE_RGB32
+EXTERN_GUID(WMMEDIASUBTYPE_RGB32,
+0xe436eb7e, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
+// 30323449-0000-0010-8000-00AA00389B71 'YV12' == MEDIASUBTYPE_I420
+EXTERN_GUID(WMMEDIASUBTYPE_I420,
+0x30323449, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
+// 56555949-0000-0010-8000-00AA00389B71 'YV12' == MEDIASUBTYPE_IYUV
+EXTERN_GUID(WMMEDIASUBTYPE_IYUV,
+0x56555949, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
+// 31313259-0000-0010-8000-00AA00389B71 'YV12' == MEDIASUBTYPE_YV12
+EXTERN_GUID(WMMEDIASUBTYPE_YV12,
+0x32315659, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
+// 32595559-0000-0010-8000-00AA00389B71 'YUY2' == MEDIASUBTYPE_YUY2
+EXTERN_GUID(WMMEDIASUBTYPE_YUY2,
+0x32595559, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
+// 59565955-0000-0010-8000-00AA00389B71 'UYVY' == MEDIASUBTYPE_UYVY
+EXTERN_GUID(WMMEDIASUBTYPE_UYVY,
+0x59565955, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
+// 55595659-0000-0010-8000-00AA00389B71 'YVYU' == MEDIASUBTYPE_YVYU
+EXTERN_GUID(WMMEDIASUBTYPE_YVYU,
+0x55595659, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
+// 39555659-0000-0010-8000-00AA00389B71 'YVU9' == MEDIASUBTYPE_YVU9
+EXTERN_GUID(WMMEDIASUBTYPE_YVU9,
+0x39555659, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
+// 3334504D-0000-0010-8000-00AA00389B71 WMMEDIASUBTYPE_MP43
+EXTERN_GUID(WMMEDIASUBTYPE_MP43,
+0x3334504D, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
+// 5334504D-0000-0010-8000-00AA00389B71 WMMEDIASUBTYPE_MP4S
+EXTERN_GUID(WMMEDIASUBTYPE_MP4S,
+0x5334504D, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
+// 31564D57-0000-0010-8000-00AA00389B71 WMMEDIASUBTYPE_WMV1
+EXTERN_GUID(WMMEDIASUBTYPE_WMV1,
+0x31564D57, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
+// 32564D57-0000-0010-8000-00AA00389B71 WMMEDIASUBTYPE_WMV2
+EXTERN_GUID(WMMEDIASUBTYPE_WMV2,
+0x32564D57, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
+// 3153534D-0000-0010-8000-00AA00389B71 WMMEDIASUBTYPE_MSS1
+EXTERN_GUID(WMMEDIASUBTYPE_MSS1,
+0x3153534D, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
+// e06d8026-db46-11cf-b4d1-00805f6cbbea WMMEDIASUBTYPE_MPEG2_VIDEO
+EXTERN_GUID(WMMEDIASUBTYPE_MPEG2_VIDEO,
+0xe06d8026, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea);
+// 00000001-0000-0010-8000-00AA00389B71 WMMEDIASUBTYPE_PCM
+EXTERN_GUID(WMMEDIASUBTYPE_PCM,
+0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
+// 00000009-0000-0010-8000-00AA00389B71 WMMEDIASUBTYPE_DRM
+EXTERN_GUID(WMMEDIASUBTYPE_DRM,
+0x00000009, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
+// 00000162-0000-0010-8000-00AA00389B71 WMMEDIASUBTYPE_WMAudioV9
+EXTERN_GUID(WMMEDIASUBTYPE_WMAudioV9,
+0x00000162, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
+// 00000163-0000-0010-8000-00AA00389B71 WMMEDIASUBTYPE_WMAudio_Lossless
+EXTERN_GUID(WMMEDIASUBTYPE_WMAudio_Lossless,
+0x00000163, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
+// 3253534D-0000-0010-8000-00AA00389B71 WMMEDIASUBTYPE_MSS2
+EXTERN_GUID(WMMEDIASUBTYPE_MSS2,
+0x3253534D, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
+// 0000000A-0000-0010-8000-00AA00389B71 WMMEDIASUBTYPE_WMSP1
+EXTERN_GUID( WMMEDIASUBTYPE_WMSP1,
+0x0000000A,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71);
+// 33564D57-0000-0010-8000-00AA00389B71 WMMEDIASUBTYPE_WMV3
+EXTERN_GUID(WMMEDIASUBTYPE_WMV3,
+0x33564D57, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
+// 00000161-0000-0010-8000-00AA00389B71 WMMEDIASUBTYPE_WMAudioV8
+EXTERN_GUID(WMMEDIASUBTYPE_WMAudioV8,
+0x00000161, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
+// 00000161-0000-0010-8000-00AA00389B71 WMMEDIASUBTYPE_WMAudioV7
+EXTERN_GUID(WMMEDIASUBTYPE_WMAudioV7,
+0x00000161, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
+// 00000161-0000-0010-8000-00AA00389B71 WMMEDIASUBTYPE_WMAudioV2
+EXTERN_GUID(WMMEDIASUBTYPE_WMAudioV2,
+0x00000161, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
+// 00000130-0000-0010-8000-00AA00389B71 WMMEDIASUBTYPE_ACELPnet
+EXTERN_GUID(WMMEDIASUBTYPE_ACELPnet,
+0x00000130, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
+// 00000050-0000-0010-8000-00AA00389B71 WMMEDIASUBTYPE_MP3
+EXTERN_GUID(WMMEDIASUBTYPE_MP3,
+0x00000055, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
+// 776257d4-c627-41cb-8f81-7ac7ff1c40cc WMMEDIASUBTYPE_WebStream
+EXTERN_GUID(WMMEDIASUBTYPE_WebStream,
+0x776257d4, 0xc627, 0x41cb, 0x8f, 0x81, 0x7a, 0xc7, 0xff, 0x1c, 0x40, 0xcc);
+
+// 05589f80-c356-11ce-bf01-00aa0055595a WMFORMAT_VideoInfo
+EXTERN_GUID(WMFORMAT_VideoInfo,
+0x05589f80, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a);
+// 05589f81-c356-11ce-bf01-00aa0055595a WMFORMAT_WaveFormatEx
+EXTERN_GUID(WMFORMAT_WaveFormatEx,
+0x05589f81, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a);
+// 5C8510F2-DEBE-4ca7-BBA5-F07A104F8DFF WMFORMAT_Script
+EXTERN_GUID(WMFORMAT_Script,
+0x5c8510f2, 0xdebe, 0x4ca7, 0xbb, 0xa5, 0xf0, 0x7a, 0x10, 0x4f, 0x8d, 0xff);
+
+// 82f38a70-c29f-11d1-97ad-00a0c95ea850 WMSCRIPTTYPE_TwoStrings
+EXTERN_GUID( WMSCRIPTTYPE_TwoStrings,
+0x82f38a70,0xc29f,0x11d1,0x97,0xad,0x00,0xa0,0xc9,0x5e,0xa8,0x50);
+
+// e06d80e3-db46-11cf-b4d1-00805f6cbbea WMFORMAT_MPEG2Video
+EXTERN_GUID(WMFORMAT_MPEG2Video,
+0xe06d80e3, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x05f, 0x6c, 0xbb, 0xea);
+
+EXTERN_GUID( CLSID_WMMUTEX_Language, 0xD6E22A00,0x35DA,0x11D1,0x90,0x34,0x00,0xA0,0xC9,0x03,0x49,0xBE );
+EXTERN_GUID( CLSID_WMMUTEX_Bitrate, 0xD6E22A01,0x35DA,0x11D1,0x90,0x34,0x00,0xA0,0xC9,0x03,0x49,0xBE );
+EXTERN_GUID( CLSID_WMMUTEX_Presentation, 0xD6E22A02,0x35DA,0x11D1,0x90,0x34,0x00,0xA0,0xC9,0x03,0x49,0xBE );
+EXTERN_GUID( CLSID_WMMUTEX_Unknown, 0xD6E22A03,0x35DA,0x11D1,0x90,0x34,0x00,0xA0,0xC9,0x03,0x49,0xBE );
+EXTERN_GUID( CLSID_WMBandwidthSharing_Exclusive, 0xaf6060aa,0x5197,0x11d2,0xb6,0xaf,0x00,0xc0,0x4f,0xd9,0x08,0xe9 );
+EXTERN_GUID( CLSID_WMBandwidthSharing_Partial, 0xaf6060ab,0x5197,0x11d2,0xb6,0xaf,0x00,0xc0,0x4f,0xd9,0x08,0xe9 );
+
+const NamedGuid MediaType[]=
+{
+ {&MEDIASUBTYPE_AIFF, TEXT("AIFF\0")},
+ {&MEDIASUBTYPE_AU, TEXT("AU\0")},
+ {&MEDIASUBTYPE_AnalogVideo_NTSC_M, TEXT("AnalogVideo_NTSC_M\0")},
+ {&MEDIASUBTYPE_AnalogVideo_PAL_B, TEXT("AnalogVideo_PAL_B\0")},
+ {&MEDIASUBTYPE_AnalogVideo_PAL_D, TEXT("AnalogVideo_PAL_D\0")},
+ {&MEDIASUBTYPE_AnalogVideo_PAL_G, TEXT("AnalogVideo_PAL_G\0")},
+ {&MEDIASUBTYPE_AnalogVideo_PAL_H, TEXT("AnalogVideo_PAL_H\0")},
+ {&MEDIASUBTYPE_AnalogVideo_PAL_I, TEXT("AnalogVideo_PAL_I\0")},
+ {&MEDIASUBTYPE_AnalogVideo_PAL_M, TEXT("AnalogVideo_PAL_M\0")},
+ {&MEDIASUBTYPE_AnalogVideo_PAL_N, TEXT("AnalogVideo_PAL_N\0")},
+ {&MEDIASUBTYPE_AnalogVideo_SECAM_B, TEXT("AnalogVideo_SECAM_B\0")},
+ {&MEDIASUBTYPE_AnalogVideo_SECAM_D, TEXT("AnalogVideo_SECAM_D\0")},
+ {&MEDIASUBTYPE_AnalogVideo_SECAM_G, TEXT("AnalogVideo_SECAM_G\0")},
+ {&MEDIASUBTYPE_AnalogVideo_SECAM_H, TEXT("AnalogVideo_SECAM_H\0")},
+ {&MEDIASUBTYPE_AnalogVideo_SECAM_K, TEXT("AnalogVideo_SECAM_K\0")},
+ {&MEDIASUBTYPE_AnalogVideo_SECAM_K1, TEXT("AnalogVideo_SECAM_K1\0")},
+ {&MEDIASUBTYPE_AnalogVideo_SECAM_L, TEXT("AnalogVideo_SECAM_L\0")},
+
+ {&MEDIASUBTYPE_ARGB1555, TEXT("ARGB1555\0")},
+ {&MEDIASUBTYPE_ARGB4444, TEXT("ARGB4444\0")},
+ {&MEDIASUBTYPE_ARGB32, TEXT("ARGB32\0")},
+ {&MEDIASUBTYPE_A2R10G10B10, TEXT("A2R10G10B10\0")},
+ {&MEDIASUBTYPE_A2B10G10R10, TEXT("A2B10G10R10\0")},
+
+ {&MEDIASUBTYPE_AYUV, TEXT("AYUV\0")},
+ {&MEDIASUBTYPE_AI44, TEXT("AI44\0")},
+ {&MEDIASUBTYPE_IA44, TEXT("IA44\0")},
+ {&MEDIASUBTYPE_NV12, TEXT("NV12\0")},
+ {&MEDIASUBTYPE_IMC1, TEXT("IMC1\0")},
+ {&MEDIASUBTYPE_IMC2, TEXT("IMC2\0")},
+ {&MEDIASUBTYPE_IMC3, TEXT("IMC3\0")},
+ {&MEDIASUBTYPE_IMC4, TEXT("IMC4\0")},
+
+ {&MEDIASUBTYPE_Asf, TEXT("Asf\0")},
+ {&MEDIASUBTYPE_Avi, TEXT("Avi\0")},
+ {&MEDIASUBTYPE_CFCC, TEXT("CFCC\0")},
+ {&MEDIASUBTYPE_CLJR, TEXT("CLJR\0")},
+ {&MEDIASUBTYPE_CPLA, TEXT("CPLA\0")},
+ {&MEDIASUBTYPE_CLPL, TEXT("CLPL\0")},
+ {&MEDIASUBTYPE_DOLBY_AC3, TEXT("DOLBY_AC3\0")},
+ {&MEDIASUBTYPE_DOLBY_AC3_SPDIF, TEXT("DOLBY_AC3_SPDIF\0")},
+ {&MEDIASUBTYPE_DVCS, TEXT("DVCS\0")},
+ {&MEDIASUBTYPE_DVD_LPCM_AUDIO, TEXT("DVD_LPCM_AUDIO\0")},
+ {&MEDIASUBTYPE_DVD_NAVIGATION_DSI, TEXT("DVD_NAVIGATION_DSI\0")},
+ {&MEDIASUBTYPE_DVD_NAVIGATION_PCI, TEXT("DVD_NAVIGATION_PCI\0")},
+ {&MEDIASUBTYPE_DVD_NAVIGATION_PROVIDER, TEXT("DVD_NAVIGATION_PROVIDER\0")},
+ {&MEDIASUBTYPE_DVD_SUBPICTURE, TEXT("DVD_SUBPICTURE\0")},
+ {&MEDIASUBTYPE_DVSD, TEXT("DVSD\0")},
+ {&MEDIASUBTYPE_DRM_Audio, TEXT("DRM_Audio\0")},
+ {&MEDIASUBTYPE_DssAudio, TEXT("DssAudio\0")},
+ {&MEDIASUBTYPE_DssVideo, TEXT("DssVideo\0")},
+ {&MEDIASUBTYPE_IF09, TEXT("IF09\0")},
+ {&MEDIASUBTYPE_IEEE_FLOAT, TEXT("IEEE_FLOAT\0")},
+ {&MEDIASUBTYPE_IJPG, TEXT("IJPG\0")},
+ {&MEDIASUBTYPE_IYUV, TEXT("IYUV\0")},
+ {&MEDIASUBTYPE_Line21_BytePair, TEXT("Line21_BytePair\0")},
+ {&MEDIASUBTYPE_Line21_GOPPacket, TEXT("Line21_GOPPacket\0")},
+ {&MEDIASUBTYPE_Line21_VBIRawData, TEXT("Line21_VBIRawData\0")},
+ {&MEDIASUBTYPE_MDVF, TEXT("MDVF\0")},
+ {&MEDIASUBTYPE_MJPG, TEXT("MJPG\0")},
+ {&MEDIASUBTYPE_MPEG1Audio, TEXT("MPEG1Audio\0")},
+ {&MEDIASUBTYPE_MPEG1AudioPayload, TEXT("MPEG1AudioPayload\0")},
+ {&MEDIASUBTYPE_MPEG1Packet, TEXT("MPEG1Packet\0")},
+ {&MEDIASUBTYPE_MPEG1Payload, TEXT("MPEG1Payload\0")},
+ {&MEDIASUBTYPE_MPEG1System, TEXT("MPEG1System\0")},
+ {&MEDIASUBTYPE_MPEG1Video, TEXT("MPEG1Video\0")},
+ {&MEDIASUBTYPE_MPEG1VideoCD, TEXT("MPEG1VideoCD\0")},
+ {&MEDIASUBTYPE_MPEG2_AUDIO, TEXT("MPEG2_AUDIO\0")},
+ {&MEDIASUBTYPE_MPEG2_PROGRAM, TEXT("MPEG2_PROGRAM\0")},
+ {&MEDIASUBTYPE_MPEG2_TRANSPORT, TEXT("MPEG2_TRANSPORT\0")},
+ {&MEDIASUBTYPE_MPEG2_VIDEO, TEXT("MPEG2_VIDEO\0")},
+ {&MEDIASUBTYPE_None, TEXT("None\0")},
+ {&MEDIASUBTYPE_Overlay, TEXT("Overlay\0")},
+ {&MEDIASUBTYPE_PCM, TEXT("PCM\0")},
+ {&MEDIASUBTYPE_PCMAudio_Obsolete, TEXT("PCMAudio_Obsolete\0")},
+ {&MEDIASUBTYPE_Plum, TEXT("Plum\0")},
+ {&MEDIASUBTYPE_QTJpeg, TEXT("QTJpeg\0")},
+ {&MEDIASUBTYPE_QTMovie, TEXT("QTMovie\0")},
+ {&MEDIASUBTYPE_QTRle, TEXT("QTRle\0")},
+ {&MEDIASUBTYPE_QTRpza, TEXT("QTRpza\0")},
+ {&MEDIASUBTYPE_QTSmc, TEXT("QTSmc\0")},
+ {&MEDIASUBTYPE_RAW_SPORT, TEXT("RAW_SPORT\0")},
+ {&MEDIASUBTYPE_RGB1, TEXT("RGB1\0")},
+ {&MEDIASUBTYPE_RGB24, TEXT("RGB24\0")},
+ {&MEDIASUBTYPE_RGB32, TEXT("RGB32\0")},
+ {&MEDIASUBTYPE_RGB4, TEXT("RGB4\0")},
+ {&MEDIASUBTYPE_RGB555, TEXT("RGB555\0")},
+ {&MEDIASUBTYPE_RGB565, TEXT("RGB565\0")},
+ {&MEDIASUBTYPE_RGB8, TEXT("RGB8\0")},
+ {&MEDIASUBTYPE_SPDIF_TAG_241h, TEXT("SPDIF_TAG_241h\0")},
+ {&MEDIASUBTYPE_TELETEXT, TEXT("TELETEXT\0")},
+ {&MEDIASUBTYPE_TVMJ, TEXT("TVMJ\0")},
+ {&MEDIASUBTYPE_UYVY, TEXT("UYVY\0")},
+ {&MEDIASUBTYPE_VPVBI, TEXT("VPVBI\0")},
+ {&MEDIASUBTYPE_VPVideo, TEXT("VPVideo\0")},
+ {&MEDIASUBTYPE_WAKE, TEXT("WAKE\0")},
+ {&MEDIASUBTYPE_WAVE, TEXT("WAVE\0")},
+ {&MEDIASUBTYPE_Y211, TEXT("Y211\0")},
+ {&MEDIASUBTYPE_Y411, TEXT("Y411\0")},
+ {&MEDIASUBTYPE_Y41P, TEXT("Y41P\0")},
+ {&MEDIASUBTYPE_YUY2, TEXT("YUY2\0")},
+ {&MEDIASUBTYPE_YV12, TEXT("YV12\0")},
+ {&MEDIASUBTYPE_YVU9, TEXT("YVU9\0")},
+ {&MEDIASUBTYPE_YVYU, TEXT("YVYU\0")},
+ {&MEDIASUBTYPE_YUYV, TEXT("YUYV\0")},
+ {&MEDIASUBTYPE_dvhd, TEXT("dvhd\0")},
+ {&MEDIASUBTYPE_dvsd, TEXT("dvsd\0")},
+ {&MEDIASUBTYPE_dvsl, TEXT("dvsl\0")},
+
+ {&MEDIATYPE_AUXLine21Data, TEXT("AUXLine21Data\0")},
+ {&MEDIATYPE_AnalogAudio, TEXT("AnalogAudio\0")},
+ {&MEDIATYPE_AnalogVideo, TEXT("AnalogVideo\0")},
+ {&MEDIATYPE_Audio, TEXT("Audio\0")},
+ {&MEDIATYPE_DVD_ENCRYPTED_PACK, TEXT("DVD_ENCRYPTED_PACK\0")},
+ {&MEDIATYPE_DVD_NAVIGATION, TEXT("DVD_NAVIGATION\0")},
+ {&MEDIATYPE_File, TEXT("File\0")},
+ {&MEDIATYPE_Interleaved, TEXT("Interleaved\0")},
+ {&MEDIATYPE_LMRT, TEXT("LMRT\0")},
+ {&MEDIATYPE_MPEG1SystemStream, TEXT("MPEG1SystemStream\0")},
+ {&MEDIATYPE_MPEG2_PES, TEXT("MPEG2_PES\0")},
+ {&MEDIATYPE_Midi, TEXT("Midi\0")},
+ {&MEDIATYPE_ScriptCommand, TEXT("ScriptCommand\0")},
+ {&MEDIATYPE_Stream, TEXT("Stream\0")},
+ {&MEDIATYPE_Text, TEXT("Text\0")},
+ {&MEDIATYPE_Timecode, TEXT("Timecode\0")},
+ {&MEDIATYPE_URL_STREAM, TEXT("URL_STREAM\0")},
+ {&MEDIATYPE_VBI, TEXT("VBI\0")},
+ {&MEDIATYPE_Video, TEXT("Video\0")},
+
+ {&WMMEDIATYPE_Audio, TEXT("WMMEDIATYPE_Audio\0")},
+ {&WMMEDIATYPE_Video, TEXT("WMMEDIATYPE_Video\0")},
+ {&WMMEDIATYPE_Script, TEXT("WMMEDIATYPE_Script\0")},
+ {&WMMEDIATYPE_Image, TEXT("WMMEDIATYPE_Image\0")},
+ {&WMMEDIATYPE_FileTransfer, TEXT("WMMEDIATYPE_FileTransfer\0")},
+ {&WMMEDIATYPE_Text, TEXT("WMMEDIATYPE_Text\0")},
+
+ {&WMMEDIASUBTYPE_Base, TEXT("WMMEDIASUBTYPE_Base\0")},
+ {&WMMEDIASUBTYPE_RGB1, TEXT("WMMEDIASUBTYPE_RGB1\0")},
+ {&WMMEDIASUBTYPE_RGB4, TEXT("WMMEDIASUBTYPE_RGB4\0")},
+ {&WMMEDIASUBTYPE_RGB8, TEXT("WMMEDIASUBTYPE_RGB8\0")},
+ {&WMMEDIASUBTYPE_RGB565, TEXT("WMMEDIASUBTYPE_RGB565\0")},
+ {&WMMEDIASUBTYPE_RGB555, TEXT("WMMEDIASUBTYPE_RGB555\0")},
+ {&WMMEDIASUBTYPE_RGB24, TEXT("WMMEDIASUBTYPE_RGB24\0")},
+ {&WMMEDIASUBTYPE_RGB32, TEXT("WMMEDIASUBTYPE_RGB32\0")},
+ {&WMMEDIASUBTYPE_I420, TEXT("WMMEDIASUBTYPE_I420\0")},
+ {&WMMEDIASUBTYPE_IYUV, TEXT("WMMEDIASUBTYPE_IYUV\0")},
+ {&WMMEDIASUBTYPE_YV12, TEXT("WMMEDIASUBTYPE_YV12\0")},
+ {&WMMEDIASUBTYPE_YUY2, TEXT("WMMEDIASUBTYPE_YUY2\0")},
+ {&WMMEDIASUBTYPE_UYVY, TEXT("WMMEDIASUBTYPE_UYVY\0")},
+ {&WMMEDIASUBTYPE_YVYU, TEXT("WMMEDIASUBTYPE_YVYU\0")},
+ {&WMMEDIASUBTYPE_YVU9, TEXT("WMMEDIASUBTYPE_YVU9\0")},
+ {&WMMEDIASUBTYPE_MP43, TEXT("WMMEDIASUBTYPE_MP43\0")},
+ {&WMMEDIASUBTYPE_MP4S, TEXT("WMMEDIASUBTYPE_MP4S\0")},
+
+ {&WMMEDIASUBTYPE_WMV1, TEXT("WMMEDIASUBTYPE_WMV1\0")},
+ {&WMMEDIASUBTYPE_WMV2, TEXT("WMMEDIASUBTYPE_WMV2\0")},
+ {&WMMEDIASUBTYPE_WMV3, TEXT("WMMEDIASUBTYPE_WMV3\0")},
+ {&WMMEDIASUBTYPE_MSS1, TEXT("WMMEDIASUBTYPE_MSS1\0")},
+ {&WMMEDIASUBTYPE_MSS2, TEXT("WMMEDIASUBTYPE_MSS2\0")},
+ {&WMMEDIASUBTYPE_MPEG2_VIDEO, TEXT("WMMEDIASUBTYPE_MPEG2_VIDEO\0")},
+ {&WMMEDIASUBTYPE_PCM, TEXT("WMMEDIASUBTYPE_PCM\0")},
+ {&WMMEDIASUBTYPE_DRM, TEXT("WMMEDIASUBTYPE_DRM\0")},
+ {&WMMEDIASUBTYPE_WMAudioV9, TEXT("WMMEDIASUBTYPE_WMAudioV9\0")},
+ {&WMMEDIASUBTYPE_WMAudio_Lossless, TEXT("WMMEDIASUBTYPE_WMAudio_Lossless\0")},
+ {&WMMEDIASUBTYPE_WMAudioV8, TEXT("WMMEDIASUBTYPE_WMAudioV8\0")},
+ {&WMMEDIASUBTYPE_WMAudioV7, TEXT("WMMEDIASUBTYPE_WMAudioV7\0")},
+ {&WMMEDIASUBTYPE_WMAudioV2, TEXT("WMMEDIASUBTYPE_WMAudioV2\0")},
+ {&WMMEDIASUBTYPE_ACELPnet, TEXT("WMMEDIASUBTYPE_ACELPnet\0")},
+ {&WMMEDIASUBTYPE_WMSP1, TEXT("WMMEDIASUBTYPE_WMSP1\0")},
+
+ {&WMFORMAT_VideoInfo, TEXT("WMFORMAT_VideoInfo\0")},
+ {&WMFORMAT_WaveFormatEx, TEXT("WMFORMAT_WaveFormatEx\0")},
+ {&WMFORMAT_Script, TEXT("WMFORMAT_Script\0")},
+ {&WMFORMAT_MPEG2Video, TEXT("WMFORMAT_MPEG2Video\0")},
+
+ {&WMSCRIPTTYPE_TwoStrings, TEXT("WMSCRIPTTYPE_TwoStrings\0")},
+
+ {&PIN_CATEGORY_ANALOGVIDEOIN, TEXT("PIN_CATEGORY_ANALOGVIDEOIN\0")},
+ {&PIN_CATEGORY_CAPTURE, TEXT("PIN_CATEGORY_CAPTURE\0")},
+ {&PIN_CATEGORY_CC, TEXT("PIN_CATEGORY_CC\0")},
+ {&PIN_CATEGORY_EDS, TEXT("PIN_CATEGORY_EDS\0")},
+ {&PIN_CATEGORY_NABTS, TEXT("PIN_CATEGORY_NABTS\0")},
+ {&PIN_CATEGORY_PREVIEW, TEXT("PIN_CATEGORY_PREVIEW\0")},
+ {&PIN_CATEGORY_STILL, TEXT("PIN_CATEGORY_STILL\0")},
+ {&PIN_CATEGORY_TELETEXT, TEXT("PIN_CATEGORY_TELETEXT\0")},
+ {&PIN_CATEGORY_TIMECODE, TEXT("PIN_CATEGORY_TIMECODE\0")},
+ {&PIN_CATEGORY_VBI, TEXT("PIN_CATEGORY_VBI\0")},
+ {&PIN_CATEGORY_VIDEOPORT, TEXT("PIN_CATEGORY_VIDEOPORT\0")},
+ {&PIN_CATEGORY_VIDEOPORT_VBI, TEXT("PIN_CATEGORY_VIDEOPORT_VBI\0")},
+
+ {&CLSID_ACMWrapper, TEXT("CLSID_ACMWrapper\0")},
+ {&CLSID_AVICo, TEXT("CLSID_AVICo\0")},
+ {&CLSID_AVIDec, TEXT("CLSID_AVIDec\0")},
+ {&CLSID_AVIDoc, TEXT("CLSID_AVIDoc\0")},
+ {&CLSID_AVIDraw, TEXT("CLSID_AVIDraw\0")},
+ {&CLSID_AVIMIDIRender, TEXT("CLSID_AVIMIDIRender\0")},
+ {&CLSID_ActiveMovieCategories, TEXT("CLSID_ActiveMovieCategories\0")},
+ {&CLSID_AnalogVideoDecoderPropertyPage, TEXT("CLSID_AnalogVideoDecoderPropertyPage\0")},
+ {&CLSID_WMAsfReader, TEXT("CLSID_WMAsfReader\0")},
+ {&CLSID_WMAsfWriter, TEXT("CLSID_WMAsfWriter\0")},
+ {&CLSID_AsyncReader, TEXT("CLSID_AsyncReader\0")},
+ {&CLSID_AudioCompressorCategory, TEXT("CLSID_AudioCompressorCategory\0")},
+ {&CLSID_AudioInputDeviceCategory, TEXT("CLSID_AudioInputDeviceCategory\0")},
+ {&CLSID_AudioProperties, TEXT("CLSID_AudioProperties\0")},
+ {&CLSID_AudioRecord, TEXT("CLSID_AudioRecord\0")},
+ {&CLSID_AudioRender, TEXT("CLSID_AudioRender\0")},
+ {&CLSID_AudioRendererCategory, TEXT("CLSID_AudioRendererCategory\0")},
+ {&CLSID_AviDest, TEXT("CLSID_AviDest\0")},
+ {&CLSID_AviMuxProptyPage, TEXT("CLSID_AviMuxProptyPage\0")},
+ {&CLSID_AviMuxProptyPage1, TEXT("CLSID_AviMuxProptyPage1\0")},
+ {&CLSID_AviReader, TEXT("CLSID_AviReader\0")},
+ {&CLSID_AviSplitter, TEXT("CLSID_AviSplitter\0")},
+ {&CLSID_CAcmCoClassManager, TEXT("CLSID_CAcmCoClassManager\0")},
+ {&CLSID_CDeviceMoniker, TEXT("CLSID_CDeviceMoniker\0")},
+ {&CLSID_CIcmCoClassManager, TEXT("CLSID_CIcmCoClassManager\0")},
+ {&CLSID_CMidiOutClassManager, TEXT("CLSID_CMidiOutClassManager\0")},
+ {&CLSID_CMpegAudioCodec, TEXT("CLSID_CMpegAudioCodec\0")},
+ {&CLSID_CMpegVideoCodec, TEXT("CLSID_CMpegVideoCodec\0")},
+ {&CLSID_CQzFilterClassManager, TEXT("CLSID_CQzFilterClassManager\0")},
+ {&CLSID_CVidCapClassManager, TEXT("CLSID_CVidCapClassManager\0")},
+ {&CLSID_CWaveOutClassManager, TEXT("CLSID_CWaveOutClassManager\0")},
+ {&CLSID_CWaveinClassManager, TEXT("CLSID_CWaveinClassManager\0")},
+ {&CLSID_CameraControlPropertyPage, TEXT("CLSID_CameraControlPropertyPage\0")},
+ {&CLSID_CaptureGraphBuilder, TEXT("CLSID_CaptureGraphBuilder\0")},
+ {&CLSID_CaptureProperties, TEXT("CLSID_CaptureProperties\0")},
+ {&CLSID_Colour, TEXT("CLSID_Colour\0")},
+ {&CLSID_CrossbarFilterPropertyPage, TEXT("CLSID_CrossbarFilterPropertyPage\0")},
+ {&CLSID_DSoundRender, TEXT("CLSID_DSoundRender\0")},
+ {&CLSID_DVDHWDecodersCategory, TEXT("CLSID_DVDHWDecodersCategory\0")},
+ {&CLSID_DVDNavigator, TEXT("CLSID_DVDNavigator\0")},
+ {&CLSID_DVDecPropertiesPage, TEXT("CLSID_DVDecPropertiesPage\0")},
+ {&CLSID_DVEncPropertiesPage, TEXT("CLSID_DVEncPropertiesPage\0")},
+ {&CLSID_DVMux, TEXT("CLSID_DVMux\0")},
+ {&CLSID_DVMuxPropertyPage, TEXT("CLSID_DVMuxPropertyPage\0")},
+ {&CLSID_DVSplitter, TEXT("CLSID_DVSplitter\0")},
+ {&CLSID_DVVideoCodec, TEXT("CLSID_DVVideoCodec\0")},
+ {&CLSID_DVVideoEnc, TEXT("CLSID_DVVideoEnc\0")},
+ {&CLSID_DirectDraw, TEXT("CLSID_DirectDraw\0")},
+ {&CLSID_DirectDrawClipper, TEXT("CLSID_DirectDrawClipper\0")},
+ {&CLSID_DirectDrawProperties, TEXT("CLSID_DirectDrawProperties\0")},
+ {&CLSID_Dither, TEXT("CLSID_Dither\0")},
+ {&CLSID_DvdGraphBuilder, TEXT("CLSID_DvdGraphBuilder\0")},
+ {&CLSID_FGControl, TEXT("CLSID_FGControl\0")},
+ {&CLSID_FileSource, TEXT("CLSID_FileSource\0")},
+ {&CLSID_FileWriter, TEXT("CLSID_FileWriter\0")},
+ {&CLSID_FilterGraph, TEXT("CLSID_FilterGraph\0")},
+ {&CLSID_FilterGraphNoThread, TEXT("CLSID_FilterGraphNoThread\0")},
+ {&CLSID_FilterMapper, TEXT("CLSID_FilterMapper\0")},
+ {&CLSID_FilterMapper2, TEXT("CLSID_FilterMapper2\0")},
+ {&CLSID_InfTee, TEXT("CLSID_InfTee\0")},
+ {&CLSID_LegacyAmFilterCategory, TEXT("CLSID_LegacyAmFilterCategory\0")},
+ {&CLSID_Line21Decoder, TEXT("CLSID_Line21Decoder\0")},
+ {&CLSID_MOVReader, TEXT("CLSID_MOVReader\0")},
+ {&CLSID_MPEG1Doc, TEXT("CLSID_MPEG1Doc\0")},
+ {&CLSID_MPEG1PacketPlayer, TEXT("CLSID_MPEG1PacketPlayer\0")},
+ {&CLSID_MPEG1Splitter, TEXT("CLSID_MPEG1Splitter\0")},
+ {&CLSID_MediaPropertyBag, TEXT("CLSID_MediaPropertyBag\0")},
+ {&CLSID_MemoryAllocator, TEXT("CLSID_MemoryAllocator\0")},
+ {&CLSID_MidiRendererCategory, TEXT("CLSID_MidiRendererCategory\0")},
+ {&CLSID_ModexProperties, TEXT("CLSID_ModexProperties\0")},
+ {&CLSID_ModexRenderer, TEXT("CLSID_ModexRenderer\0")},
+ {&CLSID_OverlayMixer, TEXT("CLSID_OverlayMixer\0")},
+ {&CLSID_PerformanceProperties, TEXT("CLSID_PerformanceProperties\0")},
+ {&CLSID_PersistMonikerPID, TEXT("CLSID_PersistMonikerPID\0")},
+ {&CLSID_ProtoFilterGraph, TEXT("CLSID_ProtoFilterGraph\0")},
+ {&CLSID_QualityProperties, TEXT("CLSID_QualityProperties\0")},
+ {&CLSID_SeekingPassThru, TEXT("CLSID_SeekingPassThru\0")},
+ {&CLSID_SmartTee, TEXT("CLSID_SmartTee\0")},
+ {&CLSID_SystemClock, TEXT("CLSID_SystemClock\0")},
+ {&CLSID_SystemDeviceEnum, TEXT("CLSID_SystemDeviceEnum\0")},
+ {&CLSID_TVAudioFilterPropertyPage, TEXT("CLSID_TVAudioFilterPropertyPage\0")},
+ {&CLSID_TVTunerFilterPropertyPage, TEXT("CLSID_TVTunerFilterPropertyPage\0")},
+ {&CLSID_TextRender, TEXT("CLSID_TextRender\0")},
+ {&CLSID_URLReader, TEXT("CLSID_URLReader\0")},
+ {&CLSID_VBISurfaces, TEXT("CLSID_VBISurfaces\0")},
+ {&CLSID_VPObject, TEXT("CLSID_VPObject\0")},
+ {&CLSID_VPVBIObject, TEXT("CLSID_VPVBIObject\0")},
+ {&CLSID_VfwCapture, TEXT("CLSID_VfwCapture\0")},
+ {&CLSID_VideoCompressorCategory, TEXT("CLSID_VideoCompressorCategory\0")},
+ {&CLSID_VideoInputDeviceCategory, TEXT("CLSID_VideoInputDeviceCategory\0")},
+ {&CLSID_VideoProcAmpPropertyPage, TEXT("CLSID_VideoProcAmpPropertyPage\0")},
+ {&CLSID_VideoRenderer, TEXT("CLSID_VideoRenderer\0")},
+ {&CLSID_VideoStreamConfigPropertyPage, TEXT("CLSID_VideoStreamConfigPropertyPage\0")},
+
+ {&CLSID_WMMUTEX_Language, TEXT("CLSID_WMMUTEX_Language\0")},
+ {&CLSID_WMMUTEX_Bitrate, TEXT("CLSID_WMMUTEX_Bitrate\0")},
+ {&CLSID_WMMUTEX_Presentation, TEXT("CLSID_WMMUTEX_Presentation\0")},
+ {&CLSID_WMMUTEX_Unknown, TEXT("CLSID_WMMUTEX_Unknown\0")},
+
+ {&CLSID_WMBandwidthSharing_Exclusive, TEXT("CLSID_WMBandwidthSharing_Exclusive\0")},
+ {&CLSID_WMBandwidthSharing_Partial, TEXT("CLSID_WMBandwidthSharing_Partial\0")},
+
+ {&FORMAT_AnalogVideo, TEXT("FORMAT_AnalogVideo\0")},
+ {&FORMAT_DVD_LPCMAudio, TEXT("FORMAT_DVD_LPCMAudio\0")},
+ {&FORMAT_DolbyAC3, TEXT("FORMAT_DolbyAC3\0")},
+ {&FORMAT_DvInfo, TEXT("FORMAT_DvInfo\0")},
+ {&FORMAT_MPEG2Audio, TEXT("FORMAT_MPEG2Audio\0")},
+ {&FORMAT_MPEG2Video, TEXT("FORMAT_MPEG2Video\0")},
+ {&FORMAT_MPEG2_VIDEO, TEXT("FORMAT_MPEG2_VIDEO\0")},
+ {&FORMAT_MPEGStreams, TEXT("FORMAT_MPEGStreams\0")},
+ {&FORMAT_MPEGVideo, TEXT("FORMAT_MPEGVideo\0")},
+ {&FORMAT_None, TEXT("FORMAT_None\0")},
+ {&FORMAT_VIDEOINFO2, TEXT("FORMAT_VIDEOINFO2\0")},
+ {&FORMAT_VideoInfo, TEXT("FORMAT_VideoInfo\0")},
+ {&FORMAT_VideoInfo2, TEXT("FORMAT_VideoInfo2\0")},
+ {&FORMAT_WaveFormatEx, TEXT("FORMAT_WaveFormatEx\0")},
+
+ {&TIME_FORMAT_BYTE, TEXT("TIME_FORMAT_BYTE\0")},
+ {&TIME_FORMAT_FIELD, TEXT("TIME_FORMAT_FIELD\0")},
+ {&TIME_FORMAT_FRAME, TEXT("TIME_FORMAT_FRAME\0")},
+ {&TIME_FORMAT_MEDIA_TIME, TEXT("TIME_FORMAT_MEDIA_TIME\0")},
+ {&TIME_FORMAT_SAMPLE, TEXT("TIME_FORMAT_SAMPLE\0")},
+
+ {&AMPROPSETID_Pin, TEXT("AMPROPSETID_Pin\0")},
+ {&AM_INTERFACESETID_Standard, TEXT("AM_INTERFACESETID_Standard\0")},
+ {&AM_KSCATEGORY_AUDIO, TEXT("AM_KSCATEGORY_AUDIO\0")},
+ {&AM_KSCATEGORY_CAPTURE, TEXT("AM_KSCATEGORY_CAPTURE\0")},
+ {&AM_KSCATEGORY_CROSSBAR, TEXT("AM_KSCATEGORY_CROSSBAR\0")},
+ {&AM_KSCATEGORY_DATACOMPRESSOR, TEXT("AM_KSCATEGORY_DATACOMPRESSOR\0")},
+ {&AM_KSCATEGORY_RENDER, TEXT("AM_KSCATEGORY_RENDER\0")},
+ {&AM_KSCATEGORY_TVAUDIO, TEXT("AM_KSCATEGORY_TVAUDIO\0")},
+ {&AM_KSCATEGORY_TVTUNER, TEXT("AM_KSCATEGORY_TVTUNER\0")},
+ {&AM_KSCATEGORY_VIDEO, TEXT("AM_KSCATEGORY_VIDEO\0")},
+ {&AM_KSPROPSETID_AC3, TEXT("AM_KSPROPSETID_AC3\0")},
+ {&AM_KSPROPSETID_CopyProt, TEXT("AM_KSPROPSETID_CopyProt\0")},
+ {&AM_KSPROPSETID_DvdSubPic, TEXT("AM_KSPROPSETID_DvdSubPic\0")},
+ {&AM_KSPROPSETID_TSRateChange, TEXT("AM_KSPROPSETID_TSRateChange\0")},
+
+ {&IID_IAMDirectSound, TEXT("IID_IAMDirectSound\0")},
+ {&IID_IAMLine21Decoder, TEXT("IID_IAMLine21Decoder\0")},
+ {&IID_IBaseVideoMixer, TEXT("IID_IBaseVideoMixer\0")},
+ {&IID_IDDVideoPortContainer, TEXT("IID_IDDVideoPortContainer\0")},
+ {&IID_IDirectDraw, TEXT("IID_IDirectDraw\0")},
+ {&IID_IDirectDraw2, TEXT("IID_IDirectDraw2\0")},
+ {&IID_IDirectDrawClipper, TEXT("IID_IDirectDrawClipper\0")},
+ {&IID_IDirectDrawColorControl, TEXT("IID_IDirectDrawColorControl\0")},
+ {&IID_IDirectDrawKernel, TEXT("IID_IDirectDrawKernel\0")},
+ {&IID_IDirectDrawPalette, TEXT("IID_IDirectDrawPalette\0")},
+ {&IID_IDirectDrawSurface, TEXT("IID_IDirectDrawSurface\0")},
+ {&IID_IDirectDrawSurface2, TEXT("IID_IDirectDrawSurface2\0")},
+ {&IID_IDirectDrawSurface3, TEXT("IID_IDirectDrawSurface3\0")},
+ {&IID_IDirectDrawSurfaceKernel, TEXT("IID_IDirectDrawSurfaceKernel\0")},
+ {&IID_IDirectDrawVideo, TEXT("IID_IDirectDrawVideo\0")},
+ {&IID_IFullScreenVideo, TEXT("IID_IFullScreenVideo\0")},
+ {&IID_IFullScreenVideoEx, TEXT("IID_IFullScreenVideoEx\0")},
+ {&IID_IKsDataTypeHandler, TEXT("IID_IKsDataTypeHandler\0")},
+ {&IID_IKsInterfaceHandler, TEXT("IID_IKsInterfaceHandler\0")},
+ {&IID_IKsPin, TEXT("IID_IKsPin\0")},
+ {&IID_IMixerPinConfig, TEXT("IID_IMixerPinConfig\0")},
+ {&IID_IMixerPinConfig2, TEXT("IID_IMixerPinConfig2\0")},
+ {&IID_IMpegAudioDecoder, TEXT("IID_IMpegAudioDecoder\0")},
+ {&IID_IQualProp, TEXT("IID_IQualProp\0")},
+ {&IID_IVPConfig, TEXT("IID_IVPConfig\0")},
+ {&IID_IVPControl, TEXT("IID_IVPControl\0")},
+ {&IID_IVPNotify, TEXT("IID_IVPNotify\0")},
+ {&IID_IVPNotify2, TEXT("IID_IVPNotify2\0")},
+ {&IID_IVPObject, TEXT("IID_IVPObject\0")},
+ {&IID_IVPVBIConfig, TEXT("IID_IVPVBIConfig\0")},
+ {&IID_IVPVBINotify, TEXT("IID_IVPVBINotify\0")},
+ {&IID_IVPVBIObject, TEXT("IID_IVPVBIObject\0")},
+
+ {&LOOK_DOWNSTREAM_ONLY, TEXT("LOOK_DOWNSTREAM_ONLY\0")},
+ {&LOOK_UPSTREAM_ONLY, TEXT("LOOK_UPSTREAM_ONLY\0")},
+ {0, 0},
+};
+
+//-----------------------------------------------------------------------------
+// GetPin
+// Find the pin of the specified format type on the given filter
+// This method leaves an outstanding reference on the pin if successful
+HRESULT GetPin(IBaseFilter* pFilter, const GUID* pFormat, PIN_DIRECTION PinDir, IPin** ppPin)
+{
+ HRESULT hr = S_OK;
+
+ if (pFilter && pFormat && ppPin)
+ {
+ IEnumPins* pIEnumPins = NULL;
+ hr = pFilter->EnumPins(&pIEnumPins);
+ if (SUCCEEDED(hr))
+ {
+ // find the pin with the specified format
+ IPin* pIPin = NULL;
+ while (S_OK == pIEnumPins->Next(1, &pIPin, NULL))
+ {
+ // match the pin direction
+ PIN_DIRECTION pinDir;
+ pIPin->QueryDirection(&pinDir);
+ if (pinDir == PinDir)
+ {
+ // match pin direction check the first media type returned from the upstream pin
+ IEnumMediaTypes* pIEnumMT = NULL;
+ hr = pIPin->EnumMediaTypes(&pIEnumMT);
+ if (SUCCEEDED(hr))
+ {
+ AM_MEDIA_TYPE* pmt = NULL;
+ hr = pIEnumMT->Next(1, &pmt, NULL);
+ if (S_OK == hr)
+ {
+ if (pmt->majortype == *pFormat)
+ {
+ // found the pin with the specified format
+ *ppPin = pIPin;
+ DeleteMediaType(pmt);
+ break;
+ }
+ else
+ {
+ DeleteMediaType(pmt);
+ }
+ }
+ pIEnumMT->Release();
+ }
+ }
+ if (pIPin) pIPin->Release(); pIPin = 0;
+ }
+
+ if (NULL == *ppPin)
+ {
+ // failed to find the named pin
+ hr = E_FAIL;
+ }
+ pIEnumPins->Release();
+ }
+ }
+ else
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+//-----------------------------------------------------------------------------
+// GetPin
+// Find the pin of the specified name on the given filter
+// This method leaves an outstanding reference on the pin if successful
+HRESULT GetPin(IBaseFilter* pFilter, LPCWSTR pName, IPin** ppPin)
+{
+ HRESULT hr = S_OK;
+
+ if (pFilter && pName && ppPin)
+ {
+ IEnumPins* pIEnumPins = NULL;
+ hr = pFilter->EnumPins(&pIEnumPins);
+ if (SUCCEEDED(hr))
+ {
+ IPin* pIPin = NULL;
+ while (S_OK == pIEnumPins->Next(1, &pIPin, NULL))
+ {
+ PIN_INFO info = {0};
+ hr = pIPin->QueryPinInfo(&info);
+ if (SUCCEEDED(hr))
+ {
+ if (info.pFilter) info.pFilter->Release(); info.pFilter = 0;
+
+ if (0 == wcsncmp(info.achName, pName, wcslen(pName)))
+ {
+ // matched the pin category
+ *ppPin = pIPin;
+ break;
+ }
+ }
+ if (pIPin) pIPin->Release(); pIPin = 0;
+ }
+ pIEnumPins->Release();
+ }
+
+ if (NULL == *ppPin)
+ {
+ // failed to find the named pin
+ hr = E_FAIL;
+ }
+ }
+ else
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+//-----------------------------------------------------------------------------
+// FindPinInterface
+// Attempt to locate the interface on the pin with the specified format or on the first pin if no
+// format is provided.
+HRESULT FindPinInterface(IBaseFilter* pFilter, const GUID* pFormat, PIN_DIRECTION PinDir, const IID& riid, void** ppvInterface)
+{
+ HRESULT hr = S_OK;
+
+ if (pFilter && ppvInterface)
+ {
+ IPin* pIPin = NULL;
+ if (pFormat)
+ {
+ hr = GetPin(pFilter, pFormat, PinDir, &pIPin);
+ }
+ else
+ {
+ IEnumPins* pIEnumPins = NULL;
+ hr = pFilter->EnumPins(&pIEnumPins);
+ if (SUCCEEDED(hr))
+ {
+ hr = pIEnumPins->Next(1, &pIPin, NULL);
+ }
+ pIEnumPins->Release();
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = pIPin->QueryInterface(riid, ppvInterface);
+ }
+ pIPin->Release();
+ }
+ else
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+std::string getStringFromGUID(const GUID *pGUID)
+{
+ int i=0;
+ // Find format GUID's name in the named guids table
+ while (MediaType[i].pguid != 0)
+ {
+ if(*pGUID == *(MediaType[i].pguid))
+ {
+ return std::string(MediaType[i].psz);
+ }
+ i++;
+ }
+
+ // return the guid if does not recognize the type
+ const int maxChar = 60;
+ LPOLESTR pwszClsid = (LPOLESTR) CoTaskMemAlloc(maxChar*2);
+ CHAR szCLSID[maxChar];
+ int nchar = StringFromGUID2(*pGUID, pwszClsid, maxChar);
+ // Convert result to ANSI
+ WideCharToMultiByte(CP_ACP, 0, pwszClsid, -1, szCLSID, nchar, NULL, NULL);
+ CoTaskMemFree(pwszClsid);
+ return std::string(szCLSID);
+}
+const GUID* getGUIDFromString(const std::string& str)
+{
+ int i=0;
+ // Find format GUID's name in the named guids table
+ while (MediaType[i].pguid != 0)
+ {
+ if(str == std::string((MediaType[i].psz)))
+ return MediaType[i].pguid;
+ i++;
+ }
+ return 0;
+}
+static std::string getErrorMessage(HRESULT hr)
+{
+ if (FAILED(hr))
+ {
+ TCHAR szErr[MAX_ERROR_TEXT_LEN];
+ DWORD res = AMGetErrorText(hr, szErr, MAX_ERROR_TEXT_LEN);
+ if (res == 0)
+ {
+ StringCchPrintf(szErr, MAX_ERROR_TEXT_LEN, "Unknown Error: 0x%2x", hr);
+ }
+ return std::string (szErr);
+ }
+ return std::string("");
+}
+
+static bool checkError(const std::string& prefix, HRESULT hr)
+{
+ if (FAILED(hr))
+ osg::notify(osg::WARN) << prefix << " " << getErrorMessage(hr) << std::endl;
+
+ if (hr == E_ABORT)
+ return false;
+ if (hr == E_FAIL)
+ return false;
+ if (hr == E_OUTOFMEMORY)
+ return false;
+ if (hr == E_POINTER)
+ return false;
+ if (hr == VFW_E_CANNOT_CONNECT)
+ return false;
+ if (hr == 0x80040256)
+ return false;
+ if (hr == 0x80040216)
+ return false;
+
+ return true;
+}
+
+bool CTextureRenderer::initBuildGraph()
+{
+ std::string prefixForMessage;
+ {
+ std::stringstream ss;
+ ss << _imageStream.get();
+ prefixForMessage = ss.str();
+ }
+
+ HRESULT hr;
+ hr = CoCreateInstance( CLSID_FilterGraph, 0, CLSCTX_INPROC,IID_IGraphBuilder, (void **)&_graphBuilder );
+ if (!checkError(prefixForMessage, hr))
+ return false;
+
+ hr = _graphBuilder->QueryInterface( IID_IMediaControl, (void **)&_mediaControl );
+ if (!checkError(prefixForMessage, hr))
+ return false;
+
+ hr = _graphBuilder->QueryInterface( IID_IMediaSeeking, (void **)&_mediaSeeking );
+ if (!checkError(prefixForMessage, hr))
+ return false;
+
+ hr = _graphBuilder->AddFilter((IBaseFilter*)this, L"Sampler");
+ if (!checkError(prefixForMessage, hr))
+ return false;
+ return true;
+}
+
+
+struct ListDeviceAvailable
+{
+ struct DeviceEntry
+ {
+ std::string _name;
+ std::string _clsid;
+ IMoniker* _device;
+ DeviceEntry(const std::string& name = "" , const std::string& clsid = "", IMoniker* device = 0) : _name(name), _clsid(clsid), _device(device) {}
+ };
+ std::vector<DeviceEntry> _listDevice;
+ IEnumMoniker* _enumMoniker;
+ ListDeviceAvailable(IEnumMoniker *enumMoniker) : _enumMoniker(enumMoniker)
+ {
+ createList();
+ }
+ ~ListDeviceAvailable()
+ {
+ for (int i = 0; i < (int)_listDevice.size(); i++)
+ if (_listDevice[i]._device)
+ _listDevice[i]._device->Release();
+ }
+
+ void displayDevicesFound(const std::string& prefixForMessage, osg::NotifySeverity serverity = osg::NOTICE) const
+ {
+ for (int i = 0; i < (int)_listDevice.size(); i++)
+ osg::notify(serverity) << prefixForMessage << " device \"" << _listDevice[i]._name << "\" clsid " << _listDevice[i]._clsid << std::endl;
+ }
+
+ DeviceEntry getDevice(const std::string& name)
+ {
+ for (int i = 0; i < (int)_listDevice.size(); i++)
+ if (_listDevice[i]._name == name)
+ return _listDevice[i];
+ //if (!_listDevice.empty())
+ // return _listDevice.front();
+ return DeviceEntry();
+ }
+
+ void createList()
+ {
+ IMoniker *device = NULL;
+ HRESULT hr;
+ // Enumerate all items associated with the moniker
+ while (_enumMoniker->Next(1, &device, NULL) == S_OK)
+ {
+ IPropertyBag *pPropBag = NULL;
+ CLSID clsidFilter;
+
+ VARIANT varName;
+ VARIANT varFilterClsid;
+
+ VariantInit(&varName);
+ VariantInit(&varFilterClsid);
+
+ // Associate moniker with a file
+ hr = device->BindToStorage(0, 0, IID_IPropertyBag,
+ (void **)&pPropBag);
+
+ // Read filter name from property bag
+ if (SUCCEEDED(hr))
+ {
+ hr = pPropBag->Read(L"FriendlyName", &varName, 0);
+ }
+
+ // Read filter's CLSID from property bag. This CLSID string will be
+ // converted to a binary CLSID and passed to AddFilter(), which will
+ // add the filter's name to the listbox and its CLSID to the listbox
+ // item's DataPtr item. When the user clicks on a filter name in
+ // the listbox, we'll read the stored CLSID, convert it to a string,
+ // and use it to find the filter's filename in the registry.
+
+ if (SUCCEEDED(hr))
+ {
+ // Read CLSID string from property bag
+ hr = pPropBag->Read(L"CLSID", &varFilterClsid, 0);
+
+ // Add filter name and CLSID to listbox
+ if (SUCCEEDED(hr))
+ {
+ hr = CLSIDFromString(varFilterClsid.bstrVal, &clsidFilter);
+ }
+ else if (hr == E_PROP_ID_UNSUPPORTED)
+ {
+ clsidFilter = GUID_NULL; // No CLSID is listed.
+ hr = S_OK;
+ }
+ }
+
+ // covert to std::string
+ _bstr_t bstr_t(varName.bstrVal);
+ std::string deviceName(bstr_t);
+ std::string deviceGUID;
+
+ // Add filter name and filename to list
+ if(SUCCEEDED(hr))
+ {
+ LPOLESTR pwszClsid;
+ CHAR szCLSID[60];
+ hr = StringFromCLSID(clsidFilter, &pwszClsid);
+ if (!FAILED(hr))
+ {
+ // Convert result to ANSI
+ WideCharToMultiByte(CP_ACP, 0, pwszClsid, -1, szCLSID, 60, NULL, NULL);
+ //osg::notify(osg::NOTICE) << "device \"" << truename << "\" id " << szCLSID << std::endl;
+ deviceGUID = std::string(szCLSID);
+ }
+ CoTaskMemFree(pwszClsid);
+ }
+
+ VariantClear(&varName);
+ VariantClear(&varFilterClsid);
+
+ // Cleanup interfaces
+ if (pPropBag) pPropBag->Release();
+
+ _listDevice.push_back(DeviceEntry(deviceName, deviceGUID, device));
+ }
+ }
+
+
+};
+
+
+struct ListCapDeviceAvailable
+{
+ typedef std::pair<AM_MEDIA_TYPE*, VIDEOINFOHEADER *> CapEntry;
+ std::vector<CapEntry> _capsList;
+ IAMStreamConfig* _config;
+ ListCapDeviceAvailable(IAMStreamConfig* config) : _config(config)
+ {
+ createList();
+ }
+ ~ListCapDeviceAvailable()
+ {
+ for (int i = 0; i < (int)_capsList.size(); i++)
+ if (_capsList[i].first)
+ DeleteMediaType(_capsList[i].first);
+ }
+
+ void displayCapsFound(const std::string& prefixForMessage = "") const
+ {
+ for (int i = 0; i < (int)_capsList.size(); i++)
+ {
+ VIDEOINFOHEADER* video= _capsList[i].second;
+ displayCap(video, prefixForMessage);
+ }
+ }
+
+ static void displayCap(VIDEOINFOHEADER* video, const std::string& prefix = "")
+ {
+ if (!video)
+ return;
+ double fps = 1.0/ (video->AvgTimePerFrame * 100.0 * 1e-9);
+ FOURCCMap fccMap(video->bmiHeader.biCompression);
+ GUID g1 = (GUID)fccMap;
+ osg::notify(osg::NOTICE) << prefix << " cap " << video->bmiHeader.biWidth << " x " << video->bmiHeader.biHeight << " bit per pixel " << video->bmiHeader.biBitCount << " (" << getStringFromGUID(&g1) << ") at " << fps << " fps" << std::endl;
+ }
+
+ std::pair<AM_MEDIA_TYPE*, VIDEOINFOHEADER *> getCaps(int width, int height, double fps)
+ {
+ std::vector<CapEntry> filterResolution;
+ for (int i = 0; i < (int)_capsList.size(); i++)
+ {
+ VIDEOINFOHEADER* video= _capsList[i].second;
+ if (video->bmiHeader.biWidth == width && video->bmiHeader.biHeight == height)
+ {
+ filterResolution.push_back(_capsList[i]);
+ }
+ }
+ // get the max fps if the fps are not reach on the desired resolution
+ typedef std::multimap<double, CapEntry> ContainerFrameRateSorted;
+ ContainerFrameRateSorted filterFrameRate;
+ for (int i = 0; i < (int)filterResolution.size(); i++)
+ {
+ VIDEOINFOHEADER* video= filterResolution[i].second;
+ double capfps = 1.0/ (video->AvgTimePerFrame * 100.0 * 1e-9);
+ double error = fabs(capfps - fps);
+ filterFrameRate.insert(std::pair<double, CapEntry>(error, filterResolution[i]));
+ }
+
+ CapEntry best = CapEntry(0,0);
+ CapEntry first = CapEntry(0,0);
+ for (ContainerFrameRateSorted::iterator it = filterFrameRate.begin();
+ it != filterFrameRate.end();
+ ++it)
+ {
+ if (first == CapEntry(0,0))
+ first = it->second;
+
+ if (it->first < 1e-3)
+ {
+ VIDEOINFOHEADER* video= it->second.second;
+ FOURCCMap fccMap(video->bmiHeader.biCompression);
+ GUID g1 = (GUID)fccMap;
+ if (getStringFromGUID(&g1) == std::string("YUY2"))
+ best = it->second;
+ }
+ }
+ if (best != CapEntry(0,0))
+ return best;
+ if (first != CapEntry(0,0))
+ return first;
+
+ if (!_capsList.empty())
+ return _capsList.front();
+ return CapEntry(0,0);
+ }
+
+ void createList()
+ {
+ std::string device = "capture";
+ // Use the IPin to get the interface:
+
+ // get the number of formats and make sure the strutucre size matches
+ int iCount, iSize;
+ VIDEO_STREAM_CONFIG_CAPS caps;
+ _config->GetNumberOfCapabilities(&iCount, &iSize);
+ if( sizeof(caps) != iSize )
+ return;
+
+ // now go through all formats and use the one you like
+ for(int i=0; i < iCount; i++)
+ {
+ // GetStreamCaps allocats the AM_MEDIA_TYPE, which must be deleted by using DeleteMediaType
+ AM_MEDIA_TYPE *pmt = NULL;
+ if( _config->GetStreamCaps(i, &pmt, (BYTE*)&caps) == S_OK )
+ {
+ if (pmt->formattype == FORMAT_VideoInfo && pmt->cbFormat >= sizeof(VIDEOINFOHEADER))
+ {
+ VIDEOINFOHEADER *video=
+ reinterpret_cast<VIDEOINFOHEADER*>(pmt->pbFormat);
+ _capsList.push_back(CapEntry(pmt, video));
+ }
+ else
+ {
+ DeleteMediaType(pmt);
+ }
+ }
+ }
+ }
+};
+
+
+bool CTextureRenderer::setupOutputSoundDevice(ICreateDevEnum* devs)
+{
+ if (!devs)
+ return false;
+
+ std::string prefixForMessage;
+ {
+ std::stringstream ss;
+ ss << _imageStream.get();
+ prefixForMessage = ss.str();
+ }
+
+ HRESULT hr;
+ std::string outputdevice = "Default DirectSound Device";
+ IEnumMoniker* audioRenderer = 0; hr = devs?devs->CreateClassEnumerator (CLSID_AudioRendererCategory, &audioRenderer, 0):0;
+ if (!checkError(prefixForMessage, hr))
+ return false;
+ ListDeviceAvailable deviceFinder(audioRenderer);
+
+ deviceFinder.displayDevicesFound(prefixForMessage + " sounddevice", osg::INFO);
+
+ ListDeviceAvailable::DeviceEntry device = deviceFinder.getDevice(outputdevice);
+ if (!device._device)
+ {
+ osg::notify(osg::WARN) << prefixForMessage << " no output sound device \"" << outputdevice << "\" found" << std::endl;
+ return false;
+ }
+
+ _soundOutputDeviceName = device._name;
+ IMoniker* mon = device._device;
+ hr = mon?mon->BindToObject(0,0,IID_IBaseFilter, (void**)&_soundOutputDevice):0;
+ checkError(prefixForMessage, hr);
+ if (FAILED(hr))
+ return false;
+
+ hr = _graphBuilder->AddFilter(_soundOutputDevice,NULL);
+ checkError(prefixForMessage, hr);
+ if (FAILED(hr))
+ {
+ if (_soundOutputDevice) _soundOutputDevice->Release(); _soundOutputDevice = 0;
+ return false;
+ }
+ return true;
+}
+
+bool CTextureRenderer::openVideoCaptureDevice(const std::string& capture, int wantWidth, int wantHeight, double wantFps)
+{
+ std::string prefixForMessage;
+ {
+ std::stringstream ss;
+ ss << _imageStream.get();
+ prefixForMessage = ss.str();
+ }
+
+ HRESULT hr;
+ ICreateDevEnum* devs = 0; hr = CoCreateInstance (CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC, IID_ICreateDevEnum, (void **) &devs);
+ if (!checkError(prefixForMessage, hr))
+ return false;
+
+ IEnumMoniker* cams = 0; hr = devs?devs->CreateClassEnumerator (CLSID_VideoInputDeviceCategory, &cams, 0):0;
+ if (!checkError(prefixForMessage, hr))
+ return false;
+
+ ListDeviceAvailable deviceFinder(cams);
+ {
+ std::stringstream ss;
+ ss << std::hex << _imageStream.get() << " capture";
+ deviceFinder.displayDevicesFound(ss.str(), osg::INFO);
+ }
+ ListDeviceAvailable::DeviceEntry device = deviceFinder.getDevice(capture);
+
+ if (!device._device)
+ {
+ osg::notify(osg::WARN) << _imageStream.get() << " no capture device \"" << capture << "\" found" << std::endl;
+ return false;
+ }
+ _videoCaptureDeviceName = device._name;
+ osg::notify(osg::NOTICE) << _imageStream.get() << " use capture device \"" << getVideoCaptureDeviceName() << "\"" << std::endl;
+
+ {
+ std::stringstream ss;
+ ss << _imageStream.get() << " \"" << getVideoCaptureDeviceName() << "\"";
+ prefixForMessage = ss.str();
+ }
+
+
+ IMoniker* mon = device._device;
+
+ hr = mon?mon->BindToObject(0,0,IID_IBaseFilter, (void**)&_videoCaptureDevice):0;
+ if (!checkError(prefixForMessage, hr))
+ return false;
+
+ IEnumPins* pins = 0; hr = _videoCaptureDevice?_videoCaptureDevice->EnumPins(&pins):0;
+ if (!checkError(prefixForMessage, hr))
+ return false;
+
+ IPin* cap = 0; hr = pins?pins->Next(1,&cap, 0):0;
+ if (pins) pins->Release(); pins = 0;
+ if (!checkError(prefixForMessage, hr))
+ return false;
+
+
+ IAMStreamConfig* capConfig = 0; hr = cap->QueryInterface( IID_IAMStreamConfig, (void **)&capConfig);
+ if (capConfig)
+ {
+ ListCapDeviceAvailable capsDevice(capConfig);
+ capsDevice.displayCapsFound(prefixForMessage);
+ ListCapDeviceAvailable::CapEntry found = capsDevice.getCaps(wantWidth, wantHeight, wantFps);
+ if (found.first)
+ {
+ ListCapDeviceAvailable::displayCap(found.second, prefixForMessage + " use ");
+ capConfig->SetFormat(found.first);
+ }
+ capConfig->Release();
+ }
+
+ hr = _graphBuilder->AddFilter(_videoCaptureDevice, L"Capture Source");
+ if (!checkError(prefixForMessage, hr))
+ return false;
+
+ IPin* rnd = 0;
+ hr = FindPin(L"In", &rnd);
+ if (!checkError(prefixForMessage, hr))
+ return false;
+
+ hr = _graphBuilder->Connect(cap,rnd);
+
+ if (rnd) rnd->Release();
+ if (cap) cap->Release();
+
+ bool result = checkError(prefixForMessage, hr);
+ return result;
+}
+
+
+bool CTextureRenderer::openSoundCaptureDevice(const std::string& capture, int nbChannels)
+{
+ std::string prefixForMessage;
+ {
+ std::stringstream ss;
+ ss << _imageStream.get();
+ prefixForMessage = ss.str();
+ }
+
+ HRESULT hr;
+ ICreateDevEnum* devs = 0; hr = CoCreateInstance (CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC, IID_ICreateDevEnum, (void **) &devs);
+ if (!checkError(prefixForMessage, hr))
+ return false;
+
+ IEnumMoniker* captureDevices = 0; hr = devs?devs->CreateClassEnumerator (CLSID_AudioInputDeviceCategory, &captureDevices, 0):0;
+ if (!checkError(prefixForMessage, hr))
+ return false;
+
+ ListDeviceAvailable deviceFinder(captureDevices);
+ {
+ std::stringstream ss;
+ ss << std::hex << _imageStream.get() << " capture sound ";
+ deviceFinder.displayDevicesFound(ss.str(), osg::INFO);
+ }
+ ListDeviceAvailable::DeviceEntry device = deviceFinder.getDevice(capture);
+
+ if (!device._device)
+ {
+ osg::notify(osg::WARN) << _imageStream.get() << " no sound capture device \"" << capture << "\" found" << std::endl;
+ return false;
+ }
+ _soundCaptureDeviceName = device._name;
+ osg::notify(osg::NOTICE) << _imageStream.get() << " use sound capture device \"" << getSoundCaptureDeviceName() << "\"" << std::endl;
+
+ {
+ std::stringstream ss;
+ ss << _imageStream.get() << " \"" << getSoundCaptureDeviceName() << "\"";
+ prefixForMessage = ss.str();
+ }
+
+
+ IMoniker* mon = device._device;
+
+ hr = mon?mon->BindToObject(0,0,IID_IBaseFilter, (void**)&_soundCaptureDevice):0;
+ if (FAILED(hr))
+ {
+ checkError(prefixForMessage, hr);
+ return false;
+ }
+
+ IAMStreamConfig* pISC = NULL;
+ hr = FindPinInterface(_soundCaptureDevice, &MEDIATYPE_Audio, PINDIR_OUTPUT, IID_IAMStreamConfig, reinterpret_cast<void**>(&pISC));
+ if (FAILED(hr))
+ {
+ checkError(prefixForMessage, hr);
+ return false;
+ }
+ // loop through all the capabilities (audio formats) and populate the control
+ int count, size;
+ hr = pISC->GetNumberOfCapabilities(&count, &size);
+ if (SUCCEEDED(hr))
+ {
+ if (sizeof(AUDIO_STREAM_CONFIG_CAPS) == size)
+ {
+ AM_MEDIA_TYPE* pmt = NULL;
+ AUDIO_STREAM_CONFIG_CAPS ascc;
+ WAVEFORMATEX* pwfex = NULL;
+
+ for (int index=0; index<count; ++index)
+ {
+ hr = pISC->GetStreamCaps(index, &pmt, reinterpret_cast<BYTE*>(&ascc));
+ if (SUCCEEDED(hr))
+ {
+ TCHAR buffer[32];
+
+ ZeroMemory(buffer, sizeof(buffer));
+
+ pwfex = (WAVEFORMATEX*)pmt->pbFormat;
+
+ // provide a useful description of the formats
+ if (1 == pwfex->nChannels)
+ {
+ StringCbPrintf(buffer, sizeof(buffer), TEXT("%d channel, %2.1fkHz, %d-bit"), (int)pwfex->nChannels, (float)pwfex->nSamplesPerSec / 1000, (int)pwfex->wBitsPerSample);
+ }
+ else
+ {
+ StringCbPrintf(buffer, sizeof(buffer), TEXT("%d channels, %2.1fkHz, %d-bit"), (int)pwfex->nChannels, (float)pwfex->nSamplesPerSec / 1000, (int)pwfex->wBitsPerSample);
+ }
+
+ // set default format
+ if (pwfex->nChannels == nbChannels)
+ {
+ pISC->SetFormat(pmt);
+ osg::notify(osg::NOTICE) << prefixForMessage << " use format " << buffer << std::endl;
+ break;
+ } else
+ osg::notify(osg::NOTICE) << prefixForMessage << buffer << std::endl;
+
+ }
+ }
+ }
+ else
+ {
+ osg::notify(osg::WARN) << prefixForMessage << " can t retrieve informations pins" << std::endl;
+ }
+ }
+ if (pISC) pISC->Release(); pISC = 0;
+ IPin* captureOutputDevicePinOut = 0; hr = _soundCaptureDevice? ::GetPin(_soundCaptureDevice,L"Capture",&captureOutputDevicePinOut) : 0;
+ if (FAILED(hr)) {
+ checkError(prefixForMessage, hr);
+ return false;
+ }
+
+ hr = _graphBuilder->AddFilter(_soundCaptureDevice, L"Sound Capture Source");
+ if (FAILED(hr))
+ {
+ checkError(prefixForMessage, hr);
+ return false;
+ }
+
+ if (!setupOutputSoundDevice(devs))
+ {
+ devs->Release(); devs = 0;
+ if (captureOutputDevicePinOut) captureOutputDevicePinOut->Release(); captureOutputDevicePinOut = 0;
+ return false;
+ }
+ devs->Release(); devs = 0;
+
+ std::string prefixForMessageSound;
+ {
+ std::stringstream ss;
+ ss << _imageStream.get() << " " << getSoundOutputDeviceName();
+ prefixForMessageSound = ss.str();
+ }
+
+ IPin* soundOutputDevicePinIn = 0;
+ hr = _soundOutputDevice->FindPin(L"Audio Input pin (rendered)", &soundOutputDevicePinIn);
+ if (FAILED(hr))
+ {
+ checkError(prefixForMessageSound, hr);
+ if (soundOutputDevicePinIn) soundOutputDevicePinIn->Release(); soundOutputDevicePinIn = 0;
+ if (captureOutputDevicePinOut) captureOutputDevicePinOut->Release(); captureOutputDevicePinOut = 0;
+ return false;
+ }
+
+ hr = _graphBuilder->Connect(captureOutputDevicePinOut, soundOutputDevicePinIn);
+
+ if (soundOutputDevicePinIn) soundOutputDevicePinIn->Release(); soundOutputDevicePinIn = 0;
+ if (captureOutputDevicePinOut) captureOutputDevicePinOut->Release(); captureOutputDevicePinOut = 0;
+
+ if (FAILED(hr))
+ {
+ checkError(prefixForMessageSound, hr);
+ return false;
+ }
+
+ return true;
+}
+
+
+bool CTextureRenderer::openCaptureDevices(const DirectShowImageStream::Options& o)
+{
+ std::string prefixForMessage;
+ {
+ std::stringstream ss;
+ ss << _imageStream.get();
+ prefixForMessage = ss.str();
+ }
+
+ DirectShowImageStream::Options options = o;
+ syncStreams(false);
+
+ for (DirectShowImageStream::Options::iterator it = options.begin(); it != options.end(); it++)
+ osg::notify(osg::NOTICE) << prefixForMessage << " option " << it->first << " = " << it->second << std::endl;
+
+ std::string soundCaptureDevice = options["captureSoundDevice"];
+ std::string videoCaptureDevice = options["captureVideoDevice"];
+
+ osg::notify(osg::NOTICE) << prefixForMessage << " try to open video capture device " << videoCaptureDevice;
+ if (!soundCaptureDevice .empty())
+ osg::notify(osg::NOTICE) << " and sound capture device " << soundCaptureDevice ;
+ osg::notify(osg::NOTICE) << std::endl;
+
+ if (!initBuildGraph())
+ return false;
+
+ int wantWidth = atoi(options["captureWantedWidth"].c_str());
+ int wantHeight = atoi(options["captureWantedHeight"].c_str());
+ float wantFps = atof(options["captureWantedFps"].c_str());
+ if (!openVideoCaptureDevice(videoCaptureDevice, wantWidth, wantHeight, wantFps))
+ return false;
+
+ if (!soundCaptureDevice.empty() && !openSoundCaptureDevice(soundCaptureDevice ))
+ osg::notify(osg::WARN) << prefixForMessage << " failed to setup sound capture device " << soundCaptureDevice << std::endl;
+
+ return true;
+}
+
+
+bool CTextureRenderer::openFile(const std::string& file)
+{
+ syncStreams(true);
+ WCHAR wFileName[MAX_PATH];
+ wFileName[MAX_PATH-1] = 0; // NULL-terminate
+ if (file.empty())
+ return false;
+
+ _filename = file;
+ std::string prefixForMessage;
+ {
+ std::stringstream ss;
+ ss << _imageStream.get() << " " << getFilename();
+ prefixForMessage = ss.str();
+ }
+
+ const char *ansistr = file.c_str();
+ int lenA = lstrlenA(ansistr);
+ int lenW;
+ BSTR unicodestr;
+
+ lenW = ::MultiByteToWideChar(CP_ACP, 0, ansistr, lenA, 0, 0);
+ if (lenW > 0)
+ {
+ // Check whether conversion was successful
+ unicodestr = ::SysAllocStringLen(0, lenW);
+ ::MultiByteToWideChar(CP_ACP, 0, ansistr, lenA, unicodestr, lenW);
+ }
+
+ (void)StringCchCopyW(wFileName, NUMELMS(wFileName), unicodestr);
+
+ // when done, free the BSTR
+ ::SysFreeString(unicodestr);
+
+ HRESULT hr;
+ if (!initBuildGraph())
+ return false;
+
+ IPin* videoOutputPin = 0;
+
+ std::string lowercase = file;
+ std::transform(lowercase.begin(), lowercase.end(), lowercase.begin(), tolower);
+ if (lowercase.rfind(".wmv") != std::string::npos)
+ {
+ hr = _graphBuilder->AddSourceFilter(wFileName, L"Windows Media source filter", &_fileSource);
+ if (!checkError(prefixForMessage, hr))
+ return false;
+ hr = _fileSource?_fileSource->FindPin(L"Raw Video 1", &videoOutputPin):0;
+ }
+ else
+ {
+ hr = _graphBuilder->AddSourceFilter(wFileName, L"File Source", &_fileSource);
+ if (!checkError(prefixForMessage, hr))
+ return false;
+ hr = _fileSource?_fileSource->FindPin(L"Output", &videoOutputPin):0;
+ }
+
+ if (!checkError(prefixForMessage, hr))
+ return false;
+
+ IPin* rnd = 0;
+ hr = FindPin(L"In", &rnd);
+ if (!checkError(prefixForMessage, hr))
+ return false;
+
+ hr = _graphBuilder->Connect(videoOutputPin, rnd);
+ if (videoOutputPin) videoOutputPin->Release(); videoOutputPin = 0;
+
+ if (rnd) rnd->Release(); rnd = 0;
+ if (!checkError(prefixForMessage, hr))
+ return false;
+
+
+ if (lowercase.rfind(".avi") == std::string::npos) // not an avi, dont try to connect sounds
+ return true;
+
+ // check if we find the sounds output pin on the streams
+ IBaseFilter* AVISpliterFilter = 0;
+ hr = _graphBuilder->FindFilterByName(L"AVI Splitter", &AVISpliterFilter);
+ if (FAILED(hr))
+ osg::notify(osg::WARN) << prefixForMessage << " did not find AVI SPlitter to connect sound, " << getErrorMessage(hr) << std::endl;
+
+ if (AVISpliterFilter)
+ {
+ IPin* soundStreamPinOut = 0;
+ hr = AVISpliterFilter->FindPin(L"Stream 01",&soundStreamPinOut);
+ AVISpliterFilter->Release(); AVISpliterFilter = 0;
+
+ if (FAILED(hr))
+ osg::notify(osg::WARN) << prefixForMessage << " can't find Stream 01 pin on AVIS Splitter, maybe the flux does have sound, " << getErrorMessage(hr) << std::endl;
+
+ if (soundStreamPinOut)
+ {
+ // connect sounds to graph
+ ICreateDevEnum* devs = 0; hr = CoCreateInstance (CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC, IID_ICreateDevEnum, (void **) &devs);
+ checkError(prefixForMessage, hr);
+ if (devs && setupOutputSoundDevice(devs))
+ {
+ devs->Release(); devs = 0;
+ std::string prefixForMessageSound;
+ {
+ std::stringstream ss;
+ ss << _imageStream.get() << " " << getSoundOutputDeviceName();
+ prefixForMessageSound = ss.str();
+ }
+
+ IPin* soundOutputDevicePinIn = 0;
+ hr = _soundOutputDevice->FindPin(L"Audio Input pin (rendered)", &soundOutputDevicePinIn);
+ checkError(prefixForMessageSound, hr);
+
+ hr = _graphBuilder->Connect(soundStreamPinOut, soundOutputDevicePinIn);
+
+ if (soundOutputDevicePinIn) soundOutputDevicePinIn->Release(); soundOutputDevicePinIn = 0;
+ if (soundStreamPinOut) soundStreamPinOut->Release(); soundStreamPinOut = 0;
+
+ if (!checkError(prefixForMessageSound, hr) && _soundOutputDevice)
+ {
+ _graphBuilder->RemoveFilter(_soundOutputDevice);
+ _soundOutputDevice->Release(); _soundOutputDevice = 0;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+
+
+//-----------------------------------------------------------------------------
+// CleanupDShow
+//-----------------------------------------------------------------------------
+void CTextureRenderer::releaseRessources()
+{
+ // Shut down the graph
+ if (_mediaControl) _mediaControl->Stop();
+ _imageStream = 0;
+
+ if (_mediaControl) _mediaControl->Release(); _mediaControl = 0;
+ if (_mediaEvent) _mediaEvent->Release(); _mediaEvent = 0;
+ if (_mediaSeeking) _mediaSeeking->Release(); _mediaSeeking = 0;
+ // remove filter outside because this is a filter too.
+}
+
+
+//-----------------------------------------------------------------------------
+// CTextureRenderer constructor
+//-----------------------------------------------------------------------------
+
+CTextureRenderer::CTextureRenderer( DirectShowImageStream* is, HRESULT* valid)
+ : CBaseVideoRenderer(__uuidof(CLSID_TextureRenderer),
+ NAME("Texture Renderer"),
+ NULL,
+ valid)
+{
+ std::string prefixForMessage;
+ {
+ std::stringstream ss;
+ ss << is;
+ prefixForMessage = ss.str();
+ }
+
+ if (FAILED(*valid))
+ checkError(prefixForMessage, *valid);
+
+ _imageStream = is;
+ _fileSource = 0;
+ _mediaControl = 0;
+ _mediaEvent = 0;
+ _mediaSeeking = 0;
+ _graphBuilder = 0;
+ _videoCaptureDevice = 0;
+ _soundOutputDevice = 0;
+ _soundCaptureDevice = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// CTextureRenderer destructor
+//-----------------------------------------------------------------------------
+CTextureRenderer::~CTextureRenderer()
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// CheckMediaType: This method forces the graph to give us an R8G8B8 video
+// type, making our copy to texture memory trivial.
+//-----------------------------------------------------------------------------
+HRESULT CTextureRenderer::CheckMediaType(const CMediaType *pmt)
+{
+ HRESULT hr = E_FAIL;
+ VIDEOINFO *pvi=0;
+
+ CheckPointer(pmt,E_POINTER);
+
+ // Reject the connection if this is not a video type
+ if( *pmt->FormatType() != FORMAT_VideoInfo ) {
+ return E_INVALIDARG;
+ }
+
+ // Only accept RGB24 video
+ pvi = (VIDEOINFO *)pmt->Format();
+
+ if (!IsEqualGUID( *pmt->Type(), MEDIATYPE_Video))
+ osg::notify(osg::WARN) << _imageStream.get() << " media type not a video format" << std::endl;
+
+
+ if( IsEqualGUID( *pmt->Subtype(), MEDIASUBTYPE_RGB24))
+ {
+ osg::notify(osg::NOTICE) << _imageStream.get() << " Texture Renderer use media " << getStringFromGUID(pmt->Subtype()) << std::endl;
+ hr = S_OK;
+ }
+ else
+ {
+ osg::notify(osg::INFO) << _imageStream.get() << " Texture Renderer check media " << getStringFromGUID(pmt->Subtype()) << std::endl;
+ }
+
+ return hr;
+}
+
+//-----------------------------------------------------------------------------
+// SetMediaType: Graph connection has been made.
+//-----------------------------------------------------------------------------
+HRESULT CTextureRenderer::SetMediaType(const CMediaType *pmt)
+{
+ // Retrive the size of this media type
+ VIDEOINFO *pviBmp; // Bitmap info header
+ pviBmp = (VIDEOINFO *)pmt->Format();
+
+ _width = pviBmp->bmiHeader.biWidth;
+ _height = abs(pviBmp->bmiHeader.biHeight);
+ _pitch = (_width * 3 + 3) & ~(3); // We are forcing RGB24
+ _imageStream->setImage(_width, _height, 1, GL_RGB, GL_BGR, GL_UNSIGNED_BYTE, 0, osg::Image::NO_DELETE);
+ return S_OK;
+}
+
+//-----------------------------------------------------------------------------
+// DoRenderSample: A sample has been delivered. Copy it to the texture.
+//-----------------------------------------------------------------------------
+HRESULT CTextureRenderer::DoRenderSample( IMediaSample * pSample )
+{
+ BYTE *pBmpBuffer; // Bitmap buffer, texture buffer
+ CheckPointer(pSample,E_POINTER);
+
+ // Get the video bitmap buffer
+ pSample->GetPointer( &pBmpBuffer );
+ if (_imageStream.valid())
+ _imageStream->setImage(_width, _height, 1, GL_RGB, GL_BGR, GL_UNSIGNED_BYTE, pBmpBuffer, osg::Image::NO_DELETE);
+ return S_OK;
+}
+
+void CTextureRenderer::syncStreams(bool state)
+{
+ if (state == true)
+ _dropFrame = !S_OK;
+ else
+ _dropFrame = S_OK;
+}
+HRESULT CTextureRenderer::ShouldDrawSampleNow(IMediaSample *sample, REFERENCE_TIME *start, REFERENCE_TIME *stop) {
+ return _dropFrame; // disable droping of frames
+}
+
+bool CTextureRenderer::StopFilters()
+{
+ HRESULT hr;
+ if (_mediaControl)
+ {
+ hr = _mediaControl->Stop();
+ if (FAILED(hr))
+ {
+ osg::notify(osg::WARN) << _imageStream.get() << " " << getErrorMessage(hr) << std::endl;
+ return false;
+ }
+ }
+ return true;
+}
+
+DirectShowImageStream::DirectShowImageStream()
+{
+ _options["captureWantedWidth"] = "1920";
+ _options["captureWantedHeight"] = "1080";
+ _options["captureWantedFps"] = "30";
+
+ HRESULT hr = CoInitialize (NULL);
+ if (FAILED(hr))
+ {
+ osg::notify(osg::WARN) << this << " error in constructor " << getErrorMessage(hr) << std::endl;
+ }
+
+}
+DirectShowImageStream::DirectShowImageStream(const DirectShowImageStream& d,const osg::CopyOp& c) : osg::ImageStream(d, c)
+{
+ // i guess it's invalid
+}
+
+DirectShowImageStream::~DirectShowImageStream()
+{
+ stop();
+ CoUninitialize();
+}
+
+bool DirectShowImageStream::openFile(const std::string& file)
+{
+ HRESULT valid = S_OK;
+ _renderer = new CTextureRenderer(this, &valid);
+ if (FAILED(valid))
+ {
+ return false;
+ }
+ if (!_renderer->openFile(file))
+ {
+ return false;
+ }
+ return true;
+}
+
+bool DirectShowImageStream::openCaptureDevices()
+{
+ HRESULT valid = S_OK;
+ _renderer = new CTextureRenderer(this, &valid);
+ if (FAILED(valid))
+ {
+ return false;
+ }
+ if (!_renderer->openCaptureDevices(_options))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+
+
+void DirectShowImageStream::play()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
+ if (_status == PLAYING)
+ return;
+
+ if (_renderer.valid() && _renderer->_mediaControl)
+ {
+ HRESULT hr;
+ hr = _renderer->_mediaControl->Run();
+ // Start the graph running;
+ if (FAILED(hr))
+ {
+ osg::notify(osg::WARN) << this << " can't run the graph " << getErrorMessage(hr) << std::endl;
+ }
+ else
+ {
+ _status = PLAYING;
+ }
+ }
+}
+
+void DirectShowImageStream::pause()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
+ if (_status == PAUSED)
+ return;
+
+ if (_renderer.valid() && _renderer->_mediaControl)
+ {
+ HRESULT hr;
+ hr = _renderer->_mediaControl->Pause();
+ if (FAILED(hr))
+ {
+ osg::notify(osg::NOTICE) << this << " " << getErrorMessage(hr) << std::endl;
+ }
+ else
+ {
+ _status = PAUSED;
+ }
+ }
+}
+
+void DirectShowImageStream::rewind()
+{
+ seek(0);
+}
+
+osg::ImageStream::StreamStatus DirectShowImageStream::getStatus()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
+ return _status;
+}
+
+void DirectShowImageStream::seek(double time)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
+ if (_renderer.valid() && _renderer->_mediaSeeking)
+ {
+ double start = time / (100 * 1e-9);
+ LONGLONG start2 = static_cast<LONGLONG>(start);
+ HRESULT hr = _renderer->_mediaSeeking->SetPositions(&start2,AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
+ if (FAILED(hr))
+ {
+ osg::notify(osg::NOTICE) << this << " " << getErrorMessage(hr) << std::endl;
+ }
+ }
+
+}
+void DirectShowImageStream::setOptions(const Options& map)
+{
+ for (Options::const_iterator it = map.begin(); it != map.end(); it++)
+ _options[it->first] = it->second;
+}
+
+void DirectShowImageStream::quit(bool waitForThreadToExit)
+{
+ stop();
+}
+
+double DirectShowImageStream::getLength() const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
+ double duration = 0;
+ if (_renderer.valid() && _renderer->_mediaSeeking)
+ {
+ LONGLONG d = 0;
+ _renderer->_mediaSeeking->GetDuration(&d);
+ duration = static_cast<double>(d);
+ duration = duration * (100.0 * 1e-9); // default unit in directshow IMediaSeeking
+ }
+ return duration;
+}
+
+double DirectShowImageStream::getFrameRate() const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
+ int frameRate = 0;
+ if (_renderer.valid())
+ _renderer->get_AvgFrameRate(&frameRate);
+ return static_cast<double>(frameRate) * 1e-2;
+}
+
+void DirectShowImageStream::setTimeMultiplier(double rate)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
+ if (_renderer.valid() && _renderer->_mediaSeeking)
+ _renderer->_mediaSeeking->SetRate(rate);
+}
+
+double DirectShowImageStream::getTimeMultiplier() const
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
+ double rate = 1.0;
+ if (_renderer.valid() && _renderer->_mediaSeeking)
+ _renderer->_mediaSeeking->GetRate(&rate);
+ return rate;
+}
+
+void DirectShowImageStream::stop()
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
+ if (!_renderer.valid())
+ return;
+ if (!_renderer->StopFilters())
+ osg::notify(osg::WARN) << this << " cant stop filters" << std::endl;
+
+ _renderer->releaseRessources();
+ // Enumerate the filters in the graph.
+ IEnumFilters *pEnum = NULL;
+ IGraphBuilder* gb = _renderer->getGraphBuilder();
+ if (!gb)
+ return;
+ HRESULT hr = gb->EnumFilters(&pEnum);
+ if (SUCCEEDED(hr))
+ {
+ IBaseFilter *pFilter = NULL;
+ while (S_OK == pEnum->Next(1, &pFilter, NULL))
+ {
+ // Remove the filter.
+ gb->RemoveFilter(pFilter);
+ // Reset the enumerator.
+ pEnum->Reset();
+ pFilter->Release();
+ }
+ pEnum->Release();
+ }
+ if (gb) gb->Release(); gb = 0;
+ _renderer = 0;
+}
View
94 src/osgPlugins/directshow/ReaderWriterDirectShow.cpp
@@ -0,0 +1,94 @@
+/* -*-c++-*- OpenSceneGraph - Copyright (C) 2009 Tharsis Software
+ *
+ * This library is open source and may be redistributed and/or modified under
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version. The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * This library 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
+ * OpenSceneGraph Public License for more details.
+ *
+ * Authors:
+ * Cedric Pinson <cedric.pinson@plopbyte.net>
+*/
+
+
+#include <osgDB/Registry>
+#include <osgDB/FileNameUtils>
+#include <osgDB/FileUtils>
+
+#include "DirectShowTexture"
+
+
+class ReaderWriterDirectShow : public osgDB::ReaderWriter
+{
+public:
+
+ ReaderWriterDirectShow()
+ {
+ }
+
+ virtual ~ReaderWriterDirectShow()
+ {
+ }
+
+ virtual const char * className() const
+ {
+ return "ReaderWriterDirectShow";
+ }
+
+ virtual ReadResult readImage(const std::string & filename, const osgDB::ReaderWriter::Options * options) const
+ {
+ const std::string ext = osgDB::getLowerCaseFileExtension(filename);
+ if (ext=="directshow") return readImage(osgDB::getNameLessExtension(filename),options);
+ return readImageStream(filename, options);
+ }
+
+ ReadResult readImageStream(const std::string& filename, const osgDB::ReaderWriter::Options * options) const
+ {
+ osg::notify(osg::INFO) << "ReaderWriterFFmpeg::readImage " << filename << std::endl;
+ const std::string path = osgDB::containsServerAddress(filename) ?
+ filename :
+ osgDB::findDataFile(filename, options);
+
+ osg::ref_ptr<DirectShowImageStream> image_stream(new DirectShowImageStream);
+
+ if (path.empty()) // try with capture
+ {
+ std::map<std::string,std::string> map;
+ if (options)
+ {
+ map["captureWantedWidth"] = options->getPluginStringData("captureWantedWidth");
+ map["captureWantedHeight"] = options->getPluginStringData("captureWantedHeight");
+ map["captureWantedFps"] = options->getPluginStringData("captureWantedFps");
+ map["captureVideoDevice"] = options->getPluginStringData("captureVideoDevice");
+ map["captureSoundDevice"] = options->getPluginStringData("captureSoundDevice");
+ map["captureSoundDeviceNbChannels"] = options->getPluginStringData("captureSoundDeviceNbChannels");
+ }
+ if (filename != "capture")
+ {
+ if (!options || (options && options->getPluginStringData("captureVideoDevice").empty()))
+ map["captureVideoDevice"] = filename;
+ }
+ image_stream->setOptions(map);
+
+ if (! image_stream->openCaptureDevices())
+ return ReadResult::FILE_NOT_HANDLED;
+ return image_stream.release();
+ }
+
+ if (! image_stream->openFile(filename))
+ return ReadResult::FILE_NOT_HANDLED;
+
+ return image_stream.release();
+ }
+
+private:
+
+};
+
+
+
+REGISTER_OSGPLUGIN(directshow, ReaderWriterDirectShow)
Please sign in to comment.
Something went wrong with that request. Please try again.