root/OpenSceneGraph/trunk/src/osgPlugins/directshow/DirectShowTexture.cpp @ 11116

Revision 11116, 70.7 kB (checked in by robert, 4 years ago)

From Trajce Nikolov, "attached is some fix for the directshow plugin. Cleans up the build warnings as well makes the code a bit safer"

Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 2009 Tharsis Software
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12 *
13 * Authors:
14 *         Cedric Pinson <cedric.pinson@plopbyte.net>
15*/
16
17#include "DirectShowTexture"
18#include <osg/notify>
19#include <osgDB/WriteFile>
20#include <sstream>
21#include <windows.h>
22#include <mmsystem.h>
23#include <comdef.h>
24
25#include <strsafe.h>
26#include <functional>
27#include <locale>
28#include <string>
29
30HRESULT GetPin(IBaseFilter* pFilter, LPCWSTR pName, IPin** ppPin);
31HRESULT GetPin(IBaseFilter* pFilter, const GUID* pFormat, PIN_DIRECTION PinDir, IPin** ppPin);
32
33
34struct NamedGuid
35{
36    const GUID *pguid;
37    const TCHAR *psz;
38};
39
40// 73646976-0000-0010-8000-00AA00389B71  'vids' == WMMEDIATYPE_Video
41EXTERN_GUID(WMMEDIATYPE_Video,
420x73646976, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
43// 73647561-0000-0010-8000-00AA00389B71  'auds' == WMMEDIATYPE_Audio
44EXTERN_GUID(WMMEDIATYPE_Audio,
450x73647561, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
46// 73636d64-0000-0010-8000-00AA00389B71  'scmd' == MEDIATYPE_Script
47EXTERN_GUID(WMMEDIATYPE_Script,
480x73636d64, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
49// 34A50FD8-8AA5-4386-81FE-A0EFE0488E31            WMMEDIATYPE_Image
50EXTERN_GUID(WMMEDIATYPE_Image,
510x34a50fd8, 0x8aa5, 0x4386, 0x81, 0xfe, 0xa0, 0xef, 0xe0, 0x48, 0x8e, 0x31);
52// D9E47579-930E-4427-ADFC-AD80F290E470  'fxfr' == WMMEDIATYPE_FileTransfer
53EXTERN_GUID(WMMEDIATYPE_FileTransfer,
540xd9e47579, 0x930e, 0x4427, 0xad, 0xfc, 0xad, 0x80, 0xf2, 0x90, 0xe4, 0x70);
55// 9BBA1EA7-5AB2-4829-BA57-0940209BCF3E      'text' == WMMEDIATYPE_Text
56EXTERN_GUID(WMMEDIATYPE_Text,
570x9bba1ea7, 0x5ab2, 0x4829, 0xba, 0x57, 0x9, 0x40, 0x20, 0x9b, 0xcf, 0x3e);
58
59// 00000000-0000-0010-8000-00AA00389B71            WMMEDIASUBTYPE_Base
60EXTERN_GUID(WMMEDIASUBTYPE_Base,
610x00000000, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
62// e436eb78-524f-11ce-9f53-0020af0ba770            MEDIASUBTYPE_RGB1
63EXTERN_GUID(WMMEDIASUBTYPE_RGB1,
640xe436eb78, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
65// e436eb79-524f-11ce-9f53-0020af0ba770            MEDIASUBTYPE_RGB4
66EXTERN_GUID(WMMEDIASUBTYPE_RGB4,
670xe436eb79, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
68// e436eb7a-524f-11ce-9f53-0020af0ba770            MEDIASUBTYPE_RGB8
69EXTERN_GUID(WMMEDIASUBTYPE_RGB8,
700xe436eb7a, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
71// e436eb7b-524f-11ce-9f53-0020af0ba770            MEDIASUBTYPE_RGB565
72EXTERN_GUID(WMMEDIASUBTYPE_RGB565,
730xe436eb7b, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
74// e436eb7c-524f-11ce-9f53-0020af0ba770            MEDIASUBTYPE_RGB555
75EXTERN_GUID(WMMEDIASUBTYPE_RGB555,
760xe436eb7c, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
77// e436eb7d-524f-11ce-9f53-0020af0ba770            MEDIASUBTYPE_RGB24
78EXTERN_GUID(WMMEDIASUBTYPE_RGB24,
790xe436eb7d, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
80// e436eb7e-524f-11ce-9f53-0020af0ba770            MEDIASUBTYPE_RGB32
81EXTERN_GUID(WMMEDIASUBTYPE_RGB32,
820xe436eb7e, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
83// 30323449-0000-0010-8000-00AA00389B71  'YV12' ==  MEDIASUBTYPE_I420
84EXTERN_GUID(WMMEDIASUBTYPE_I420,
850x30323449, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
86// 56555949-0000-0010-8000-00AA00389B71  'YV12' ==  MEDIASUBTYPE_IYUV
87EXTERN_GUID(WMMEDIASUBTYPE_IYUV,
880x56555949, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
89// 31313259-0000-0010-8000-00AA00389B71  'YV12' ==  MEDIASUBTYPE_YV12
90EXTERN_GUID(WMMEDIASUBTYPE_YV12,
910x32315659, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
92// 32595559-0000-0010-8000-00AA00389B71  'YUY2' == MEDIASUBTYPE_YUY2
93EXTERN_GUID(WMMEDIASUBTYPE_YUY2,
940x32595559, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
95// 59565955-0000-0010-8000-00AA00389B71  'UYVY' ==  MEDIASUBTYPE_UYVY
96EXTERN_GUID(WMMEDIASUBTYPE_UYVY,
970x59565955, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
98// 55595659-0000-0010-8000-00AA00389B71  'YVYU' == MEDIASUBTYPE_YVYU
99EXTERN_GUID(WMMEDIASUBTYPE_YVYU,
1000x55595659, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
101// 39555659-0000-0010-8000-00AA00389B71  'YVU9' == MEDIASUBTYPE_YVU9
102EXTERN_GUID(WMMEDIASUBTYPE_YVU9,
1030x39555659, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
104// 3334504D-0000-0010-8000-00AA00389B71            WMMEDIASUBTYPE_MP43
105EXTERN_GUID(WMMEDIASUBTYPE_MP43,
1060x3334504D, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
107// 5334504D-0000-0010-8000-00AA00389B71            WMMEDIASUBTYPE_MP4S
108EXTERN_GUID(WMMEDIASUBTYPE_MP4S,
1090x5334504D, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
110// 31564D57-0000-0010-8000-00AA00389B71            WMMEDIASUBTYPE_WMV1
111EXTERN_GUID(WMMEDIASUBTYPE_WMV1,
1120x31564D57, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
113// 32564D57-0000-0010-8000-00AA00389B71            WMMEDIASUBTYPE_WMV2
114EXTERN_GUID(WMMEDIASUBTYPE_WMV2,
1150x32564D57, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
116// 3153534D-0000-0010-8000-00AA00389B71            WMMEDIASUBTYPE_MSS1
117EXTERN_GUID(WMMEDIASUBTYPE_MSS1,
1180x3153534D, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
119// e06d8026-db46-11cf-b4d1-00805f6cbbea            WMMEDIASUBTYPE_MPEG2_VIDEO
120EXTERN_GUID(WMMEDIASUBTYPE_MPEG2_VIDEO,
1210xe06d8026, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea);
122// 00000001-0000-0010-8000-00AA00389B71            WMMEDIASUBTYPE_PCM
123EXTERN_GUID(WMMEDIASUBTYPE_PCM,
1240x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
125// 00000009-0000-0010-8000-00AA00389B71            WMMEDIASUBTYPE_DRM
126EXTERN_GUID(WMMEDIASUBTYPE_DRM,
1270x00000009, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
128// 00000162-0000-0010-8000-00AA00389B71            WMMEDIASUBTYPE_WMAudioV9
129EXTERN_GUID(WMMEDIASUBTYPE_WMAudioV9,
1300x00000162, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
131// 00000163-0000-0010-8000-00AA00389B71            WMMEDIASUBTYPE_WMAudio_Lossless
132EXTERN_GUID(WMMEDIASUBTYPE_WMAudio_Lossless,
1330x00000163, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
134// 3253534D-0000-0010-8000-00AA00389B71            WMMEDIASUBTYPE_MSS2
135EXTERN_GUID(WMMEDIASUBTYPE_MSS2,
1360x3253534D, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
137// 0000000A-0000-0010-8000-00AA00389B71        WMMEDIASUBTYPE_WMSP1
138EXTERN_GUID( WMMEDIASUBTYPE_WMSP1,
1390x0000000A,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71);
140// 33564D57-0000-0010-8000-00AA00389B71            WMMEDIASUBTYPE_WMV3
141EXTERN_GUID(WMMEDIASUBTYPE_WMV3,
1420x33564D57, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
143// 00000161-0000-0010-8000-00AA00389B71            WMMEDIASUBTYPE_WMAudioV8
144EXTERN_GUID(WMMEDIASUBTYPE_WMAudioV8,
1450x00000161, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
146// 00000161-0000-0010-8000-00AA00389B71            WMMEDIASUBTYPE_WMAudioV7
147EXTERN_GUID(WMMEDIASUBTYPE_WMAudioV7,
1480x00000161, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
149// 00000161-0000-0010-8000-00AA00389B71            WMMEDIASUBTYPE_WMAudioV2
150EXTERN_GUID(WMMEDIASUBTYPE_WMAudioV2,
1510x00000161, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
152// 00000130-0000-0010-8000-00AA00389B71            WMMEDIASUBTYPE_ACELPnet
153EXTERN_GUID(WMMEDIASUBTYPE_ACELPnet,
1540x00000130, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
155// 00000050-0000-0010-8000-00AA00389B71            WMMEDIASUBTYPE_MP3
156EXTERN_GUID(WMMEDIASUBTYPE_MP3,
1570x00000055, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
158// 776257d4-c627-41cb-8f81-7ac7ff1c40cc            WMMEDIASUBTYPE_WebStream
159EXTERN_GUID(WMMEDIASUBTYPE_WebStream,
1600x776257d4, 0xc627, 0x41cb, 0x8f, 0x81, 0x7a, 0xc7, 0xff, 0x1c, 0x40, 0xcc);
161
162// 05589f80-c356-11ce-bf01-00aa0055595a        WMFORMAT_VideoInfo
163EXTERN_GUID(WMFORMAT_VideoInfo,
1640x05589f80, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a);
165// 05589f81-c356-11ce-bf01-00aa0055595a        WMFORMAT_WaveFormatEx
166EXTERN_GUID(WMFORMAT_WaveFormatEx,
1670x05589f81, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a);
168// 5C8510F2-DEBE-4ca7-BBA5-F07A104F8DFF        WMFORMAT_Script
169EXTERN_GUID(WMFORMAT_Script,
1700x5c8510f2, 0xdebe, 0x4ca7, 0xbb, 0xa5, 0xf0, 0x7a, 0x10, 0x4f, 0x8d, 0xff);
171
172// 82f38a70-c29f-11d1-97ad-00a0c95ea850        WMSCRIPTTYPE_TwoStrings
173EXTERN_GUID( WMSCRIPTTYPE_TwoStrings,
1740x82f38a70,0xc29f,0x11d1,0x97,0xad,0x00,0xa0,0xc9,0x5e,0xa8,0x50);
175
176// e06d80e3-db46-11cf-b4d1-00805f6cbbea        WMFORMAT_MPEG2Video
177EXTERN_GUID(WMFORMAT_MPEG2Video,
1780xe06d80e3, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x05f, 0x6c, 0xbb, 0xea);
179
180EXTERN_GUID( CLSID_WMMUTEX_Language, 0xD6E22A00,0x35DA,0x11D1,0x90,0x34,0x00,0xA0,0xC9,0x03,0x49,0xBE );
181EXTERN_GUID( CLSID_WMMUTEX_Bitrate, 0xD6E22A01,0x35DA,0x11D1,0x90,0x34,0x00,0xA0,0xC9,0x03,0x49,0xBE );
182EXTERN_GUID( CLSID_WMMUTEX_Presentation, 0xD6E22A02,0x35DA,0x11D1,0x90,0x34,0x00,0xA0,0xC9,0x03,0x49,0xBE );
183EXTERN_GUID( CLSID_WMMUTEX_Unknown, 0xD6E22A03,0x35DA,0x11D1,0x90,0x34,0x00,0xA0,0xC9,0x03,0x49,0xBE );
184EXTERN_GUID( CLSID_WMBandwidthSharing_Exclusive, 0xaf6060aa,0x5197,0x11d2,0xb6,0xaf,0x00,0xc0,0x4f,0xd9,0x08,0xe9 );
185EXTERN_GUID( CLSID_WMBandwidthSharing_Partial, 0xaf6060ab,0x5197,0x11d2,0xb6,0xaf,0x00,0xc0,0x4f,0xd9,0x08,0xe9 );
186
187const NamedGuid MediaType[]=
188{
189    {&MEDIASUBTYPE_AIFF, TEXT("AIFF\0")},
190    {&MEDIASUBTYPE_AU, TEXT("AU\0")},
191    {&MEDIASUBTYPE_AnalogVideo_NTSC_M, TEXT("AnalogVideo_NTSC_M\0")},
192    {&MEDIASUBTYPE_AnalogVideo_PAL_B, TEXT("AnalogVideo_PAL_B\0")},
193    {&MEDIASUBTYPE_AnalogVideo_PAL_D, TEXT("AnalogVideo_PAL_D\0")},
194    {&MEDIASUBTYPE_AnalogVideo_PAL_G, TEXT("AnalogVideo_PAL_G\0")},
195    {&MEDIASUBTYPE_AnalogVideo_PAL_H, TEXT("AnalogVideo_PAL_H\0")},
196    {&MEDIASUBTYPE_AnalogVideo_PAL_I, TEXT("AnalogVideo_PAL_I\0")},
197    {&MEDIASUBTYPE_AnalogVideo_PAL_M, TEXT("AnalogVideo_PAL_M\0")},
198    {&MEDIASUBTYPE_AnalogVideo_PAL_N, TEXT("AnalogVideo_PAL_N\0")},
199    {&MEDIASUBTYPE_AnalogVideo_SECAM_B, TEXT("AnalogVideo_SECAM_B\0")},
200    {&MEDIASUBTYPE_AnalogVideo_SECAM_D, TEXT("AnalogVideo_SECAM_D\0")},
201    {&MEDIASUBTYPE_AnalogVideo_SECAM_G, TEXT("AnalogVideo_SECAM_G\0")},
202    {&MEDIASUBTYPE_AnalogVideo_SECAM_H, TEXT("AnalogVideo_SECAM_H\0")},
203    {&MEDIASUBTYPE_AnalogVideo_SECAM_K, TEXT("AnalogVideo_SECAM_K\0")},
204    {&MEDIASUBTYPE_AnalogVideo_SECAM_K1, TEXT("AnalogVideo_SECAM_K1\0")},
205    {&MEDIASUBTYPE_AnalogVideo_SECAM_L, TEXT("AnalogVideo_SECAM_L\0")},
206
207    {&MEDIASUBTYPE_ARGB1555, TEXT("ARGB1555\0")},
208    {&MEDIASUBTYPE_ARGB4444, TEXT("ARGB4444\0")},
209    {&MEDIASUBTYPE_ARGB32, TEXT("ARGB32\0")},
210    {&MEDIASUBTYPE_A2R10G10B10, TEXT("A2R10G10B10\0")},
211    {&MEDIASUBTYPE_A2B10G10R10, TEXT("A2B10G10R10\0")},
212
213    {&MEDIASUBTYPE_AYUV, TEXT("AYUV\0")},
214    {&MEDIASUBTYPE_AI44, TEXT("AI44\0")},
215    {&MEDIASUBTYPE_IA44, TEXT("IA44\0")},
216    {&MEDIASUBTYPE_NV12, TEXT("NV12\0")},
217    {&MEDIASUBTYPE_IMC1, TEXT("IMC1\0")},
218    {&MEDIASUBTYPE_IMC2, TEXT("IMC2\0")},
219    {&MEDIASUBTYPE_IMC3, TEXT("IMC3\0")},
220    {&MEDIASUBTYPE_IMC4, TEXT("IMC4\0")},
221
222    {&MEDIASUBTYPE_Asf, TEXT("Asf\0")},
223    {&MEDIASUBTYPE_Avi, TEXT("Avi\0")},
224    {&MEDIASUBTYPE_CFCC, TEXT("CFCC\0")},
225    {&MEDIASUBTYPE_CLJR, TEXT("CLJR\0")},
226    {&MEDIASUBTYPE_CPLA, TEXT("CPLA\0")},
227    {&MEDIASUBTYPE_CLPL, TEXT("CLPL\0")},
228    {&MEDIASUBTYPE_DOLBY_AC3, TEXT("DOLBY_AC3\0")},
229    {&MEDIASUBTYPE_DOLBY_AC3_SPDIF, TEXT("DOLBY_AC3_SPDIF\0")},
230    {&MEDIASUBTYPE_DVCS, TEXT("DVCS\0")},
231    {&MEDIASUBTYPE_DVD_LPCM_AUDIO, TEXT("DVD_LPCM_AUDIO\0")},
232    {&MEDIASUBTYPE_DVD_NAVIGATION_DSI, TEXT("DVD_NAVIGATION_DSI\0")},
233    {&MEDIASUBTYPE_DVD_NAVIGATION_PCI, TEXT("DVD_NAVIGATION_PCI\0")},
234    {&MEDIASUBTYPE_DVD_NAVIGATION_PROVIDER, TEXT("DVD_NAVIGATION_PROVIDER\0")},
235    {&MEDIASUBTYPE_DVD_SUBPICTURE, TEXT("DVD_SUBPICTURE\0")},
236    {&MEDIASUBTYPE_DVSD, TEXT("DVSD\0")},
237    {&MEDIASUBTYPE_DRM_Audio, TEXT("DRM_Audio\0")},
238    {&MEDIASUBTYPE_DssAudio, TEXT("DssAudio\0")},
239    {&MEDIASUBTYPE_DssVideo, TEXT("DssVideo\0")},
240    {&MEDIASUBTYPE_IF09, TEXT("IF09\0")},
241    {&MEDIASUBTYPE_IEEE_FLOAT, TEXT("IEEE_FLOAT\0")},
242    {&MEDIASUBTYPE_IJPG, TEXT("IJPG\0")},
243    {&MEDIASUBTYPE_IYUV, TEXT("IYUV\0")},
244    {&MEDIASUBTYPE_Line21_BytePair, TEXT("Line21_BytePair\0")},
245    {&MEDIASUBTYPE_Line21_GOPPacket, TEXT("Line21_GOPPacket\0")},
246    {&MEDIASUBTYPE_Line21_VBIRawData, TEXT("Line21_VBIRawData\0")},
247    {&MEDIASUBTYPE_MDVF, TEXT("MDVF\0")},
248    {&MEDIASUBTYPE_MJPG, TEXT("MJPG\0")},
249    {&MEDIASUBTYPE_MPEG1Audio, TEXT("MPEG1Audio\0")},
250    {&MEDIASUBTYPE_MPEG1AudioPayload, TEXT("MPEG1AudioPayload\0")},
251    {&MEDIASUBTYPE_MPEG1Packet, TEXT("MPEG1Packet\0")},
252    {&MEDIASUBTYPE_MPEG1Payload, TEXT("MPEG1Payload\0")},
253    {&MEDIASUBTYPE_MPEG1System, TEXT("MPEG1System\0")},
254    {&MEDIASUBTYPE_MPEG1Video, TEXT("MPEG1Video\0")},
255    {&MEDIASUBTYPE_MPEG1VideoCD, TEXT("MPEG1VideoCD\0")},
256    {&MEDIASUBTYPE_MPEG2_AUDIO, TEXT("MPEG2_AUDIO\0")},
257    {&MEDIASUBTYPE_MPEG2_PROGRAM, TEXT("MPEG2_PROGRAM\0")},
258    {&MEDIASUBTYPE_MPEG2_TRANSPORT, TEXT("MPEG2_TRANSPORT\0")},
259    {&MEDIASUBTYPE_MPEG2_VIDEO, TEXT("MPEG2_VIDEO\0")},
260    {&MEDIASUBTYPE_None, TEXT("None\0")},
261    {&MEDIASUBTYPE_Overlay, TEXT("Overlay\0")},
262    {&MEDIASUBTYPE_PCM, TEXT("PCM\0")},
263    {&MEDIASUBTYPE_PCMAudio_Obsolete, TEXT("PCMAudio_Obsolete\0")},
264    {&MEDIASUBTYPE_Plum, TEXT("Plum\0")},
265    {&MEDIASUBTYPE_QTJpeg, TEXT("QTJpeg\0")},
266    {&MEDIASUBTYPE_QTMovie, TEXT("QTMovie\0")},
267    {&MEDIASUBTYPE_QTRle, TEXT("QTRle\0")},
268    {&MEDIASUBTYPE_QTRpza, TEXT("QTRpza\0")},
269    {&MEDIASUBTYPE_QTSmc, TEXT("QTSmc\0")},
270    {&MEDIASUBTYPE_RAW_SPORT, TEXT("RAW_SPORT\0")},
271    {&MEDIASUBTYPE_RGB1, TEXT("RGB1\0")},
272    {&MEDIASUBTYPE_RGB24, TEXT("RGB24\0")},
273    {&MEDIASUBTYPE_RGB32, TEXT("RGB32\0")},
274    {&MEDIASUBTYPE_RGB4, TEXT("RGB4\0")},
275    {&MEDIASUBTYPE_RGB555, TEXT("RGB555\0")},
276    {&MEDIASUBTYPE_RGB565, TEXT("RGB565\0")},
277    {&MEDIASUBTYPE_RGB8, TEXT("RGB8\0")},
278    {&MEDIASUBTYPE_SPDIF_TAG_241h, TEXT("SPDIF_TAG_241h\0")},
279    {&MEDIASUBTYPE_TELETEXT, TEXT("TELETEXT\0")},
280    {&MEDIASUBTYPE_TVMJ, TEXT("TVMJ\0")},
281    {&MEDIASUBTYPE_UYVY, TEXT("UYVY\0")},
282    {&MEDIASUBTYPE_VPVBI, TEXT("VPVBI\0")},
283    {&MEDIASUBTYPE_VPVideo, TEXT("VPVideo\0")},
284    {&MEDIASUBTYPE_WAKE, TEXT("WAKE\0")},
285    {&MEDIASUBTYPE_WAVE, TEXT("WAVE\0")},
286    {&MEDIASUBTYPE_Y211, TEXT("Y211\0")},
287    {&MEDIASUBTYPE_Y411, TEXT("Y411\0")},
288    {&MEDIASUBTYPE_Y41P, TEXT("Y41P\0")},
289    {&MEDIASUBTYPE_YUY2, TEXT("YUY2\0")},
290    {&MEDIASUBTYPE_YV12, TEXT("YV12\0")},
291    {&MEDIASUBTYPE_YVU9, TEXT("YVU9\0")},
292    {&MEDIASUBTYPE_YVYU, TEXT("YVYU\0")},
293    {&MEDIASUBTYPE_YUYV, TEXT("YUYV\0")},
294    {&MEDIASUBTYPE_dvhd, TEXT("dvhd\0")},
295    {&MEDIASUBTYPE_dvsd, TEXT("dvsd\0")},
296    {&MEDIASUBTYPE_dvsl, TEXT("dvsl\0")},
297
298    {&MEDIATYPE_AUXLine21Data, TEXT("AUXLine21Data\0")},
299    {&MEDIATYPE_AnalogAudio, TEXT("AnalogAudio\0")},
300    {&MEDIATYPE_AnalogVideo, TEXT("AnalogVideo\0")},
301    {&MEDIATYPE_Audio, TEXT("Audio\0")},
302    {&MEDIATYPE_DVD_ENCRYPTED_PACK, TEXT("DVD_ENCRYPTED_PACK\0")},
303    {&MEDIATYPE_DVD_NAVIGATION, TEXT("DVD_NAVIGATION\0")},
304    {&MEDIATYPE_File, TEXT("File\0")},
305    {&MEDIATYPE_Interleaved, TEXT("Interleaved\0")},
306    {&MEDIATYPE_LMRT, TEXT("LMRT\0")},
307    {&MEDIATYPE_MPEG1SystemStream, TEXT("MPEG1SystemStream\0")},
308    {&MEDIATYPE_MPEG2_PES, TEXT("MPEG2_PES\0")},
309    {&MEDIATYPE_Midi, TEXT("Midi\0")},
310    {&MEDIATYPE_ScriptCommand, TEXT("ScriptCommand\0")},
311    {&MEDIATYPE_Stream, TEXT("Stream\0")},
312    {&MEDIATYPE_Text, TEXT("Text\0")},
313    {&MEDIATYPE_Timecode, TEXT("Timecode\0")},
314    {&MEDIATYPE_URL_STREAM, TEXT("URL_STREAM\0")},
315    {&MEDIATYPE_VBI, TEXT("VBI\0")},
316    {&MEDIATYPE_Video, TEXT("Video\0")},
317
318    {&WMMEDIATYPE_Audio,  TEXT("WMMEDIATYPE_Audio\0")},
319    {&WMMEDIATYPE_Video,  TEXT("WMMEDIATYPE_Video\0")},
320    {&WMMEDIATYPE_Script, TEXT("WMMEDIATYPE_Script\0")},
321    {&WMMEDIATYPE_Image,  TEXT("WMMEDIATYPE_Image\0")},
322    {&WMMEDIATYPE_FileTransfer, TEXT("WMMEDIATYPE_FileTransfer\0")},
323    {&WMMEDIATYPE_Text,   TEXT("WMMEDIATYPE_Text\0")},
324
325    {&WMMEDIASUBTYPE_Base, TEXT("WMMEDIASUBTYPE_Base\0")},
326    {&WMMEDIASUBTYPE_RGB1, TEXT("WMMEDIASUBTYPE_RGB1\0")},
327    {&WMMEDIASUBTYPE_RGB4, TEXT("WMMEDIASUBTYPE_RGB4\0")},
328    {&WMMEDIASUBTYPE_RGB8, TEXT("WMMEDIASUBTYPE_RGB8\0")},
329    {&WMMEDIASUBTYPE_RGB565, TEXT("WMMEDIASUBTYPE_RGB565\0")},
330    {&WMMEDIASUBTYPE_RGB555, TEXT("WMMEDIASUBTYPE_RGB555\0")},
331    {&WMMEDIASUBTYPE_RGB24, TEXT("WMMEDIASUBTYPE_RGB24\0")},
332    {&WMMEDIASUBTYPE_RGB32, TEXT("WMMEDIASUBTYPE_RGB32\0")},
333    {&WMMEDIASUBTYPE_I420, TEXT("WMMEDIASUBTYPE_I420\0")},
334    {&WMMEDIASUBTYPE_IYUV, TEXT("WMMEDIASUBTYPE_IYUV\0")},
335    {&WMMEDIASUBTYPE_YV12, TEXT("WMMEDIASUBTYPE_YV12\0")},
336    {&WMMEDIASUBTYPE_YUY2, TEXT("WMMEDIASUBTYPE_YUY2\0")},
337    {&WMMEDIASUBTYPE_UYVY, TEXT("WMMEDIASUBTYPE_UYVY\0")},
338    {&WMMEDIASUBTYPE_YVYU, TEXT("WMMEDIASUBTYPE_YVYU\0")},
339    {&WMMEDIASUBTYPE_YVU9, TEXT("WMMEDIASUBTYPE_YVU9\0")},
340    {&WMMEDIASUBTYPE_MP43, TEXT("WMMEDIASUBTYPE_MP43\0")},
341    {&WMMEDIASUBTYPE_MP4S, TEXT("WMMEDIASUBTYPE_MP4S\0")},
342
343    {&WMMEDIASUBTYPE_WMV1, TEXT("WMMEDIASUBTYPE_WMV1\0")},
344    {&WMMEDIASUBTYPE_WMV2, TEXT("WMMEDIASUBTYPE_WMV2\0")},
345    {&WMMEDIASUBTYPE_WMV3, TEXT("WMMEDIASUBTYPE_WMV3\0")},
346    {&WMMEDIASUBTYPE_MSS1, TEXT("WMMEDIASUBTYPE_MSS1\0")},
347    {&WMMEDIASUBTYPE_MSS2, TEXT("WMMEDIASUBTYPE_MSS2\0")},
348    {&WMMEDIASUBTYPE_MPEG2_VIDEO,  TEXT("WMMEDIASUBTYPE_MPEG2_VIDEO\0")},
349    {&WMMEDIASUBTYPE_PCM, TEXT("WMMEDIASUBTYPE_PCM\0")},
350    {&WMMEDIASUBTYPE_DRM, TEXT("WMMEDIASUBTYPE_DRM\0")},
351    {&WMMEDIASUBTYPE_WMAudioV9, TEXT("WMMEDIASUBTYPE_WMAudioV9\0")},
352    {&WMMEDIASUBTYPE_WMAudio_Lossless, TEXT("WMMEDIASUBTYPE_WMAudio_Lossless\0")},
353    {&WMMEDIASUBTYPE_WMAudioV8, TEXT("WMMEDIASUBTYPE_WMAudioV8\0")},
354    {&WMMEDIASUBTYPE_WMAudioV7, TEXT("WMMEDIASUBTYPE_WMAudioV7\0")},
355    {&WMMEDIASUBTYPE_WMAudioV2, TEXT("WMMEDIASUBTYPE_WMAudioV2\0")},
356    {&WMMEDIASUBTYPE_ACELPnet, TEXT("WMMEDIASUBTYPE_ACELPnet\0")},
357    {&WMMEDIASUBTYPE_WMSP1, TEXT("WMMEDIASUBTYPE_WMSP1\0")},
358
359    {&WMFORMAT_VideoInfo,    TEXT("WMFORMAT_VideoInfo\0")},
360    {&WMFORMAT_WaveFormatEx, TEXT("WMFORMAT_WaveFormatEx\0")},
361    {&WMFORMAT_Script,       TEXT("WMFORMAT_Script\0")},
362    {&WMFORMAT_MPEG2Video,   TEXT("WMFORMAT_MPEG2Video\0")},
363
364    {&WMSCRIPTTYPE_TwoStrings, TEXT("WMSCRIPTTYPE_TwoStrings\0")},
365
366    {&PIN_CATEGORY_ANALOGVIDEOIN, TEXT("PIN_CATEGORY_ANALOGVIDEOIN\0")},
367    {&PIN_CATEGORY_CAPTURE, TEXT("PIN_CATEGORY_CAPTURE\0")},
368    {&PIN_CATEGORY_CC, TEXT("PIN_CATEGORY_CC\0")},
369    {&PIN_CATEGORY_EDS, TEXT("PIN_CATEGORY_EDS\0")},
370    {&PIN_CATEGORY_NABTS, TEXT("PIN_CATEGORY_NABTS\0")},
371    {&PIN_CATEGORY_PREVIEW, TEXT("PIN_CATEGORY_PREVIEW\0")},
372    {&PIN_CATEGORY_STILL, TEXT("PIN_CATEGORY_STILL\0")},
373    {&PIN_CATEGORY_TELETEXT, TEXT("PIN_CATEGORY_TELETEXT\0")},
374    {&PIN_CATEGORY_TIMECODE, TEXT("PIN_CATEGORY_TIMECODE\0")},
375    {&PIN_CATEGORY_VBI, TEXT("PIN_CATEGORY_VBI\0")},
376    {&PIN_CATEGORY_VIDEOPORT, TEXT("PIN_CATEGORY_VIDEOPORT\0")},
377    {&PIN_CATEGORY_VIDEOPORT_VBI, TEXT("PIN_CATEGORY_VIDEOPORT_VBI\0")},
378
379    {&CLSID_ACMWrapper, TEXT("CLSID_ACMWrapper\0")},
380    {&CLSID_AVICo, TEXT("CLSID_AVICo\0")},
381    {&CLSID_AVIDec, TEXT("CLSID_AVIDec\0")},
382    {&CLSID_AVIDoc, TEXT("CLSID_AVIDoc\0")},
383    {&CLSID_AVIDraw, TEXT("CLSID_AVIDraw\0")},
384    {&CLSID_AVIMIDIRender, TEXT("CLSID_AVIMIDIRender\0")},
385    {&CLSID_ActiveMovieCategories, TEXT("CLSID_ActiveMovieCategories\0")},
386    {&CLSID_AnalogVideoDecoderPropertyPage, TEXT("CLSID_AnalogVideoDecoderPropertyPage\0")},
387    {&CLSID_WMAsfReader, TEXT("CLSID_WMAsfReader\0")},
388    {&CLSID_WMAsfWriter, TEXT("CLSID_WMAsfWriter\0")},
389    {&CLSID_AsyncReader, TEXT("CLSID_AsyncReader\0")},
390    {&CLSID_AudioCompressorCategory, TEXT("CLSID_AudioCompressorCategory\0")},
391    {&CLSID_AudioInputDeviceCategory, TEXT("CLSID_AudioInputDeviceCategory\0")},
392    {&CLSID_AudioProperties, TEXT("CLSID_AudioProperties\0")},
393    {&CLSID_AudioRecord, TEXT("CLSID_AudioRecord\0")},
394    {&CLSID_AudioRender, TEXT("CLSID_AudioRender\0")},
395    {&CLSID_AudioRendererCategory, TEXT("CLSID_AudioRendererCategory\0")},
396    {&CLSID_AviDest, TEXT("CLSID_AviDest\0")},
397    {&CLSID_AviMuxProptyPage, TEXT("CLSID_AviMuxProptyPage\0")},
398    {&CLSID_AviMuxProptyPage1, TEXT("CLSID_AviMuxProptyPage1\0")},
399    {&CLSID_AviReader, TEXT("CLSID_AviReader\0")},
400    {&CLSID_AviSplitter, TEXT("CLSID_AviSplitter\0")},
401    {&CLSID_CAcmCoClassManager, TEXT("CLSID_CAcmCoClassManager\0")},
402    {&CLSID_CDeviceMoniker, TEXT("CLSID_CDeviceMoniker\0")},
403    {&CLSID_CIcmCoClassManager, TEXT("CLSID_CIcmCoClassManager\0")},
404    {&CLSID_CMidiOutClassManager, TEXT("CLSID_CMidiOutClassManager\0")},
405    {&CLSID_CMpegAudioCodec, TEXT("CLSID_CMpegAudioCodec\0")},
406    {&CLSID_CMpegVideoCodec, TEXT("CLSID_CMpegVideoCodec\0")},
407    {&CLSID_CQzFilterClassManager, TEXT("CLSID_CQzFilterClassManager\0")},
408    {&CLSID_CVidCapClassManager, TEXT("CLSID_CVidCapClassManager\0")},
409    {&CLSID_CWaveOutClassManager, TEXT("CLSID_CWaveOutClassManager\0")},
410    {&CLSID_CWaveinClassManager, TEXT("CLSID_CWaveinClassManager\0")},
411    {&CLSID_CameraControlPropertyPage, TEXT("CLSID_CameraControlPropertyPage\0")},
412    {&CLSID_CaptureGraphBuilder, TEXT("CLSID_CaptureGraphBuilder\0")},
413    {&CLSID_CaptureProperties, TEXT("CLSID_CaptureProperties\0")},
414    {&CLSID_Colour, TEXT("CLSID_Colour\0")},
415    {&CLSID_CrossbarFilterPropertyPage, TEXT("CLSID_CrossbarFilterPropertyPage\0")},
416    {&CLSID_DSoundRender, TEXT("CLSID_DSoundRender\0")},
417    {&CLSID_DVDHWDecodersCategory, TEXT("CLSID_DVDHWDecodersCategory\0")},
418    {&CLSID_DVDNavigator, TEXT("CLSID_DVDNavigator\0")},
419    {&CLSID_DVDecPropertiesPage, TEXT("CLSID_DVDecPropertiesPage\0")},
420    {&CLSID_DVEncPropertiesPage, TEXT("CLSID_DVEncPropertiesPage\0")},
421    {&CLSID_DVMux, TEXT("CLSID_DVMux\0")},
422    {&CLSID_DVMuxPropertyPage, TEXT("CLSID_DVMuxPropertyPage\0")},
423    {&CLSID_DVSplitter, TEXT("CLSID_DVSplitter\0")},
424    {&CLSID_DVVideoCodec, TEXT("CLSID_DVVideoCodec\0")},
425    {&CLSID_DVVideoEnc, TEXT("CLSID_DVVideoEnc\0")},
426    {&CLSID_DirectDraw, TEXT("CLSID_DirectDraw\0")},
427    {&CLSID_DirectDrawClipper, TEXT("CLSID_DirectDrawClipper\0")},
428    {&CLSID_DirectDrawProperties, TEXT("CLSID_DirectDrawProperties\0")},
429    {&CLSID_Dither, TEXT("CLSID_Dither\0")},
430    {&CLSID_DvdGraphBuilder, TEXT("CLSID_DvdGraphBuilder\0")},
431    {&CLSID_FGControl, TEXT("CLSID_FGControl\0")},
432    {&CLSID_FileSource, TEXT("CLSID_FileSource\0")},
433    {&CLSID_FileWriter, TEXT("CLSID_FileWriter\0")},
434    {&CLSID_FilterGraph, TEXT("CLSID_FilterGraph\0")},
435    {&CLSID_FilterGraphNoThread, TEXT("CLSID_FilterGraphNoThread\0")},
436    {&CLSID_FilterMapper, TEXT("CLSID_FilterMapper\0")},
437    {&CLSID_FilterMapper2, TEXT("CLSID_FilterMapper2\0")},
438    {&CLSID_InfTee, TEXT("CLSID_InfTee\0")},
439    {&CLSID_LegacyAmFilterCategory, TEXT("CLSID_LegacyAmFilterCategory\0")},
440    {&CLSID_Line21Decoder, TEXT("CLSID_Line21Decoder\0")},
441    {&CLSID_MOVReader, TEXT("CLSID_MOVReader\0")},
442    {&CLSID_MPEG1Doc, TEXT("CLSID_MPEG1Doc\0")},
443    {&CLSID_MPEG1PacketPlayer, TEXT("CLSID_MPEG1PacketPlayer\0")},
444    {&CLSID_MPEG1Splitter, TEXT("CLSID_MPEG1Splitter\0")},
445    {&CLSID_MediaPropertyBag, TEXT("CLSID_MediaPropertyBag\0")},
446    {&CLSID_MemoryAllocator, TEXT("CLSID_MemoryAllocator\0")},
447    {&CLSID_MidiRendererCategory, TEXT("CLSID_MidiRendererCategory\0")},
448    {&CLSID_ModexProperties, TEXT("CLSID_ModexProperties\0")},
449    {&CLSID_ModexRenderer, TEXT("CLSID_ModexRenderer\0")},
450    {&CLSID_OverlayMixer, TEXT("CLSID_OverlayMixer\0")},
451    {&CLSID_PerformanceProperties, TEXT("CLSID_PerformanceProperties\0")},
452    {&CLSID_PersistMonikerPID, TEXT("CLSID_PersistMonikerPID\0")},
453    {&CLSID_ProtoFilterGraph, TEXT("CLSID_ProtoFilterGraph\0")},
454    {&CLSID_QualityProperties, TEXT("CLSID_QualityProperties\0")},
455    {&CLSID_SeekingPassThru, TEXT("CLSID_SeekingPassThru\0")},
456    {&CLSID_SmartTee, TEXT("CLSID_SmartTee\0")},
457    {&CLSID_SystemClock, TEXT("CLSID_SystemClock\0")},
458    {&CLSID_SystemDeviceEnum, TEXT("CLSID_SystemDeviceEnum\0")},
459    {&CLSID_TVAudioFilterPropertyPage, TEXT("CLSID_TVAudioFilterPropertyPage\0")},
460    {&CLSID_TVTunerFilterPropertyPage, TEXT("CLSID_TVTunerFilterPropertyPage\0")},
461    {&CLSID_TextRender, TEXT("CLSID_TextRender\0")},
462    {&CLSID_URLReader, TEXT("CLSID_URLReader\0")},
463    {&CLSID_VBISurfaces, TEXT("CLSID_VBISurfaces\0")},
464    {&CLSID_VPObject, TEXT("CLSID_VPObject\0")},
465    {&CLSID_VPVBIObject, TEXT("CLSID_VPVBIObject\0")},
466    {&CLSID_VfwCapture, TEXT("CLSID_VfwCapture\0")},
467    {&CLSID_VideoCompressorCategory, TEXT("CLSID_VideoCompressorCategory\0")},
468    {&CLSID_VideoInputDeviceCategory, TEXT("CLSID_VideoInputDeviceCategory\0")},
469    {&CLSID_VideoProcAmpPropertyPage, TEXT("CLSID_VideoProcAmpPropertyPage\0")},
470    {&CLSID_VideoRenderer, TEXT("CLSID_VideoRenderer\0")},
471    {&CLSID_VideoStreamConfigPropertyPage, TEXT("CLSID_VideoStreamConfigPropertyPage\0")},
472
473    {&CLSID_WMMUTEX_Language,      TEXT("CLSID_WMMUTEX_Language\0")},
474    {&CLSID_WMMUTEX_Bitrate,       TEXT("CLSID_WMMUTEX_Bitrate\0")},
475    {&CLSID_WMMUTEX_Presentation,  TEXT("CLSID_WMMUTEX_Presentation\0")},
476    {&CLSID_WMMUTEX_Unknown,       TEXT("CLSID_WMMUTEX_Unknown\0")},
477
478    {&CLSID_WMBandwidthSharing_Exclusive, TEXT("CLSID_WMBandwidthSharing_Exclusive\0")},
479    {&CLSID_WMBandwidthSharing_Partial,   TEXT("CLSID_WMBandwidthSharing_Partial\0")},
480
481    {&FORMAT_AnalogVideo, TEXT("FORMAT_AnalogVideo\0")},
482    {&FORMAT_DVD_LPCMAudio, TEXT("FORMAT_DVD_LPCMAudio\0")},
483    {&FORMAT_DolbyAC3, TEXT("FORMAT_DolbyAC3\0")},
484    {&FORMAT_DvInfo, TEXT("FORMAT_DvInfo\0")},
485    {&FORMAT_MPEG2Audio, TEXT("FORMAT_MPEG2Audio\0")},
486    {&FORMAT_MPEG2Video, TEXT("FORMAT_MPEG2Video\0")},
487    {&FORMAT_MPEG2_VIDEO, TEXT("FORMAT_MPEG2_VIDEO\0")},
488    {&FORMAT_MPEGStreams, TEXT("FORMAT_MPEGStreams\0")},
489    {&FORMAT_MPEGVideo, TEXT("FORMAT_MPEGVideo\0")},
490    {&FORMAT_None, TEXT("FORMAT_None\0")},
491    {&FORMAT_VIDEOINFO2, TEXT("FORMAT_VIDEOINFO2\0")},
492    {&FORMAT_VideoInfo, TEXT("FORMAT_VideoInfo\0")},
493    {&FORMAT_VideoInfo2, TEXT("FORMAT_VideoInfo2\0")},
494    {&FORMAT_WaveFormatEx, TEXT("FORMAT_WaveFormatEx\0")},
495
496    {&TIME_FORMAT_BYTE, TEXT("TIME_FORMAT_BYTE\0")},
497    {&TIME_FORMAT_FIELD, TEXT("TIME_FORMAT_FIELD\0")},
498    {&TIME_FORMAT_FRAME, TEXT("TIME_FORMAT_FRAME\0")},
499    {&TIME_FORMAT_MEDIA_TIME, TEXT("TIME_FORMAT_MEDIA_TIME\0")},
500    {&TIME_FORMAT_SAMPLE, TEXT("TIME_FORMAT_SAMPLE\0")},
501
502    {&AMPROPSETID_Pin, TEXT("AMPROPSETID_Pin\0")},
503    {&AM_INTERFACESETID_Standard, TEXT("AM_INTERFACESETID_Standard\0")},
504    {&AM_KSCATEGORY_AUDIO, TEXT("AM_KSCATEGORY_AUDIO\0")},
505    {&AM_KSCATEGORY_CAPTURE, TEXT("AM_KSCATEGORY_CAPTURE\0")},
506    {&AM_KSCATEGORY_CROSSBAR, TEXT("AM_KSCATEGORY_CROSSBAR\0")},
507    {&AM_KSCATEGORY_DATACOMPRESSOR, TEXT("AM_KSCATEGORY_DATACOMPRESSOR\0")},
508    {&AM_KSCATEGORY_RENDER, TEXT("AM_KSCATEGORY_RENDER\0")},
509    {&AM_KSCATEGORY_TVAUDIO, TEXT("AM_KSCATEGORY_TVAUDIO\0")},
510    {&AM_KSCATEGORY_TVTUNER, TEXT("AM_KSCATEGORY_TVTUNER\0")},
511    {&AM_KSCATEGORY_VIDEO, TEXT("AM_KSCATEGORY_VIDEO\0")},
512    {&AM_KSPROPSETID_AC3, TEXT("AM_KSPROPSETID_AC3\0")},
513    {&AM_KSPROPSETID_CopyProt, TEXT("AM_KSPROPSETID_CopyProt\0")},
514    {&AM_KSPROPSETID_DvdSubPic, TEXT("AM_KSPROPSETID_DvdSubPic\0")},
515    {&AM_KSPROPSETID_TSRateChange, TEXT("AM_KSPROPSETID_TSRateChange\0")},
516
517    {&IID_IAMDirectSound, TEXT("IID_IAMDirectSound\0")},
518    {&IID_IAMLine21Decoder, TEXT("IID_IAMLine21Decoder\0")},
519    {&IID_IBaseVideoMixer, TEXT("IID_IBaseVideoMixer\0")},
520    {&IID_IDDVideoPortContainer, TEXT("IID_IDDVideoPortContainer\0")},
521    {&IID_IDirectDraw, TEXT("IID_IDirectDraw\0")},
522    {&IID_IDirectDraw2, TEXT("IID_IDirectDraw2\0")},
523    {&IID_IDirectDrawClipper, TEXT("IID_IDirectDrawClipper\0")},
524    {&IID_IDirectDrawColorControl, TEXT("IID_IDirectDrawColorControl\0")},
525    {&IID_IDirectDrawKernel, TEXT("IID_IDirectDrawKernel\0")},
526    {&IID_IDirectDrawPalette, TEXT("IID_IDirectDrawPalette\0")},
527    {&IID_IDirectDrawSurface, TEXT("IID_IDirectDrawSurface\0")},
528    {&IID_IDirectDrawSurface2, TEXT("IID_IDirectDrawSurface2\0")},
529    {&IID_IDirectDrawSurface3, TEXT("IID_IDirectDrawSurface3\0")},
530    {&IID_IDirectDrawSurfaceKernel, TEXT("IID_IDirectDrawSurfaceKernel\0")},
531    {&IID_IDirectDrawVideo, TEXT("IID_IDirectDrawVideo\0")},
532    {&IID_IFullScreenVideo, TEXT("IID_IFullScreenVideo\0")},
533    {&IID_IFullScreenVideoEx, TEXT("IID_IFullScreenVideoEx\0")},
534    {&IID_IKsDataTypeHandler, TEXT("IID_IKsDataTypeHandler\0")},
535    {&IID_IKsInterfaceHandler, TEXT("IID_IKsInterfaceHandler\0")},
536    {&IID_IKsPin, TEXT("IID_IKsPin\0")},
537    {&IID_IMixerPinConfig, TEXT("IID_IMixerPinConfig\0")},
538    {&IID_IMixerPinConfig2, TEXT("IID_IMixerPinConfig2\0")},
539    {&IID_IMpegAudioDecoder, TEXT("IID_IMpegAudioDecoder\0")},
540    {&IID_IQualProp, TEXT("IID_IQualProp\0")},
541    {&IID_IVPConfig, TEXT("IID_IVPConfig\0")},
542    {&IID_IVPControl, TEXT("IID_IVPControl\0")},
543    {&IID_IVPNotify, TEXT("IID_IVPNotify\0")},
544    {&IID_IVPNotify2, TEXT("IID_IVPNotify2\0")},
545    {&IID_IVPObject, TEXT("IID_IVPObject\0")},
546    {&IID_IVPVBIConfig, TEXT("IID_IVPVBIConfig\0")},
547    {&IID_IVPVBINotify, TEXT("IID_IVPVBINotify\0")},
548    {&IID_IVPVBIObject, TEXT("IID_IVPVBIObject\0")},
549
550    {&LOOK_DOWNSTREAM_ONLY, TEXT("LOOK_DOWNSTREAM_ONLY\0")},
551    {&LOOK_UPSTREAM_ONLY, TEXT("LOOK_UPSTREAM_ONLY\0")},
552    {0, 0},
553};
554
555//-----------------------------------------------------------------------------
556// GetPin
557// Find the pin of the specified format type on the given filter
558// This method leaves an outstanding reference on the pin if successful
559HRESULT GetPin(IBaseFilter* pFilter, const GUID* pFormat, PIN_DIRECTION PinDir, IPin** ppPin)
560{
561    HRESULT hr = S_OK;
562
563    if (pFilter && pFormat && ppPin)
564    {
565        IEnumPins* pIEnumPins = NULL;
566        hr = pFilter->EnumPins(&pIEnumPins);
567        if (SUCCEEDED(hr))
568        {
569            // find the pin with the specified format
570            IPin* pIPin = NULL;
571            while (S_OK == pIEnumPins->Next(1, &pIPin, NULL))
572            {
573                // match the pin direction
574                PIN_DIRECTION pinDir;
575                pIPin->QueryDirection(&pinDir);
576                if (pinDir == PinDir)
577                {
578                    // match pin direction check the first media type returned from the upstream pin
579                    IEnumMediaTypes* pIEnumMT = NULL;
580                    hr = pIPin->EnumMediaTypes(&pIEnumMT);
581                    if (SUCCEEDED(hr))
582                    {
583                        AM_MEDIA_TYPE* pmt = NULL;
584                        hr = pIEnumMT->Next(1, &pmt, NULL);
585                        if (S_OK == hr)
586                        {
587                            if (pmt->majortype == *pFormat)
588                            {
589                                // found the pin with the specified format
590                                *ppPin = pIPin;
591                                DeleteMediaType(pmt);
592                                break;
593                            }
594                            else
595                            {
596                                DeleteMediaType(pmt);
597                            }
598                        }
599                        pIEnumMT->Release();
600                    }
601                }
602                if (pIPin) pIPin->Release(); pIPin = 0;
603            }
604
605            if (NULL == *ppPin)
606            {
607                // failed to find the named pin
608                hr = E_FAIL;
609            }
610        pIEnumPins->Release();
611        }
612    }
613    else
614    {
615        hr = E_INVALIDARG;
616    }
617
618    return hr;
619}
620//-----------------------------------------------------------------------------
621// GetPin
622// Find the pin of the specified name on the given filter
623// This method leaves an outstanding reference on the pin if successful
624HRESULT GetPin(IBaseFilter* pFilter, LPCWSTR pName, IPin** ppPin)
625{
626    HRESULT hr = S_OK;
627
628    if (pFilter && pName && ppPin)
629    {
630        IEnumPins* pIEnumPins = NULL;
631        hr = pFilter->EnumPins(&pIEnumPins);
632        if (SUCCEEDED(hr))
633        {
634            IPin* pIPin = NULL;
635            while (S_OK == pIEnumPins->Next(1, &pIPin, NULL))
636            {
637                PIN_INFO info = {0};
638                hr = pIPin->QueryPinInfo(&info);
639                if (SUCCEEDED(hr))
640                {
641                    if (info.pFilter) info.pFilter->Release(); info.pFilter = 0;
642
643                    if (0 == wcsncmp(info.achName, pName, wcslen(pName)))
644                    {
645                        // matched the pin category
646                        *ppPin = pIPin;
647                        break;
648                    }
649                }
650                if (pIPin) pIPin->Release(); pIPin = 0;
651            }
652            pIEnumPins->Release();
653        }
654
655        if (NULL == *ppPin)
656        {
657            // failed to find the named pin
658            hr = E_FAIL;
659        }
660    }
661    else
662    {
663        hr = E_INVALIDARG;
664    }
665
666    return hr;
667}
668
669//-----------------------------------------------------------------------------
670// FindPinInterface
671// Attempt to locate the interface on the pin with the specified format or on the first pin if no
672// format is provided.
673HRESULT FindPinInterface(IBaseFilter* pFilter, const GUID* pFormat, PIN_DIRECTION PinDir, const IID& riid, void** ppvInterface)
674{
675    HRESULT hr = S_OK;
676
677    if (pFilter && ppvInterface)
678    {
679        IPin* pIPin = NULL;
680        if (pFormat)
681        {
682            hr = GetPin(pFilter, pFormat, PinDir, &pIPin);
683        }
684        else
685        {
686            IEnumPins* pIEnumPins = NULL;
687            hr = pFilter->EnumPins(&pIEnumPins);
688            if (SUCCEEDED(hr))
689            {
690                hr = pIEnumPins->Next(1, &pIPin, NULL);
691            }
692            pIEnumPins->Release();
693        }
694
695        if (SUCCEEDED(hr))
696        {
697            hr = pIPin->QueryInterface(riid, ppvInterface);
698        }
699        pIPin->Release();
700    }
701    else
702    {
703        hr = E_INVALIDARG;
704    }
705   
706    return hr;
707}
708
709std::string getStringFromGUID(const GUID *pGUID)
710{
711    int i=0;
712    // Find format GUID's name in the named guids table
713    while (MediaType[i].pguid != 0)
714    {
715        if(*pGUID == *(MediaType[i].pguid))
716        {
717            return std::string(MediaType[i].psz);
718        }
719        i++;
720    }
721
722    // return the guid if does not recognize the type
723    const int maxChar = 60;
724    LPOLESTR pwszClsid = (LPOLESTR) CoTaskMemAlloc(maxChar*2);
725    CHAR  szCLSID[maxChar];
726    int nchar = StringFromGUID2(*pGUID, pwszClsid, maxChar);
727    // Convert result to ANSI
728    WideCharToMultiByte(CP_ACP, 0, pwszClsid, -1, szCLSID, nchar, NULL, NULL);
729    CoTaskMemFree(pwszClsid);
730    return std::string(szCLSID);
731}
732const GUID* getGUIDFromString(const std::string& str)
733{
734    int i=0;
735    // Find format GUID's name in the named guids table
736    while (MediaType[i].pguid != 0)
737    {
738        if(str == std::string((MediaType[i].psz)))
739            return MediaType[i].pguid;
740        i++;
741    }
742    return 0;
743}
744static std::string getErrorMessage(HRESULT hr)
745{
746    if (FAILED(hr))
747    {
748        TCHAR szErr[MAX_ERROR_TEXT_LEN];
749        DWORD res = AMGetErrorText(hr, szErr, MAX_ERROR_TEXT_LEN);
750        if (res == 0)
751        {
752            StringCchPrintf(szErr, MAX_ERROR_TEXT_LEN, "Unknown Error: 0x%2x", hr);
753        }
754        return std::string (szErr);
755    }
756    return std::string("");
757}
758
759static bool checkError(const std::string& prefix, HRESULT hr)
760{
761    if (FAILED(hr))
762        osg::notify(osg::WARN) << prefix << " " << getErrorMessage(hr) << std::endl;
763
764    if (hr == E_ABORT)
765        return false;
766    if (hr == E_FAIL)
767        return false;
768    if (hr == E_OUTOFMEMORY)
769        return false;
770    if (hr == E_POINTER)
771        return false;
772    if (hr == VFW_E_CANNOT_CONNECT)
773        return false;
774    if (hr == 0x80040256)
775        return false;
776    if (hr == 0x80040216)
777        return false;
778
779    return true;
780}
781
782bool CTextureRenderer::initBuildGraph()
783{
784    std::string prefixForMessage;
785    {
786    std::stringstream ss;
787    ss << _imageStream.get();
788    prefixForMessage = ss.str();
789    }
790
791    HRESULT hr;
792    hr = CoCreateInstance( CLSID_FilterGraph, 0, CLSCTX_INPROC,IID_IGraphBuilder, (void **)&_graphBuilder );
793    if (!checkError(prefixForMessage, hr))
794        return false;
795
796    hr = _graphBuilder->QueryInterface( IID_IMediaControl, (void **)&_mediaControl );
797    if (!checkError(prefixForMessage, hr))
798        return false;
799
800    hr = _graphBuilder->QueryInterface( IID_IMediaSeeking, (void **)&_mediaSeeking );
801    if (!checkError(prefixForMessage, hr))
802        return false;
803
804    hr = _graphBuilder->AddFilter((IBaseFilter*)this, L"Sampler");
805    if (!checkError(prefixForMessage, hr))
806        return false;
807    return true;
808}
809
810
811struct ListDeviceAvailable
812{
813    struct DeviceEntry
814    {
815        std::string _name;
816        std::string _clsid;
817        IMoniker* _device;
818        DeviceEntry(const std::string& name = "" , const std::string& clsid = "", IMoniker* device = 0) : _name(name), _clsid(clsid), _device(device) {}
819    };
820    std::vector<DeviceEntry> _listDevice;
821    IEnumMoniker* _enumMoniker;
822    ListDeviceAvailable(IEnumMoniker *enumMoniker) : _enumMoniker(enumMoniker)
823    {
824        createList();
825    }
826    ~ListDeviceAvailable()
827    {
828        for (int i = 0; i < (int)_listDevice.size(); i++)
829            if (_listDevice[i]._device)
830                _listDevice[i]._device->Release();
831    }
832
833    void displayDevicesFound(const std::string& prefixForMessage, osg::NotifySeverity serverity = osg::NOTICE) const
834    {
835        for (int i = 0; i < (int)_listDevice.size(); i++)
836            osg::notify(serverity) << prefixForMessage << " device \"" << _listDevice[i]._name << "\" clsid " << _listDevice[i]._clsid << std::endl;
837    }
838
839    DeviceEntry getDevice(const std::string& name)
840    {
841        for (int i = 0; i < (int)_listDevice.size(); i++)
842            if (_listDevice[i]._name == name)
843                return _listDevice[i];
844        //if (!_listDevice.empty())
845        //    return _listDevice.front();
846        return DeviceEntry();
847    }
848
849    void createList()
850    {
851        IMoniker *device = NULL;
852        HRESULT hr;
853        // Enumerate all items associated with the moniker
854        while (_enumMoniker->Next(1, &device, NULL) == S_OK)
855        {
856            IPropertyBag *pPropBag = NULL;
857            CLSID clsidFilter;
858
859            VARIANT varName;
860            VARIANT varFilterClsid;
861
862            VariantInit(&varName);
863            VariantInit(&varFilterClsid);
864
865            // Associate moniker with a file
866            hr = device->BindToStorage(0, 0, IID_IPropertyBag,
867                                         (void **)&pPropBag);
868
869            // Read filter name from property bag
870            if (SUCCEEDED(hr))
871            {
872                hr = pPropBag->Read(L"FriendlyName", &varName, 0);
873            }
874
875            // Read filter's CLSID from property bag.  This CLSID string will be
876            // converted to a binary CLSID and passed to AddFilter(), which will
877            // add the filter's name to the listbox and its CLSID to the listbox
878            // item's DataPtr item.  When the user clicks on a filter name in
879            // the listbox, we'll read the stored CLSID, convert it to a string,
880            // and use it to find the filter's filename in the registry.
881
882            if (SUCCEEDED(hr))
883            {
884                // Read CLSID string from property bag
885                hr = pPropBag->Read(L"CLSID", &varFilterClsid, 0);
886
887                // Add filter name and CLSID to listbox
888                if (SUCCEEDED(hr))
889                {
890                    hr = CLSIDFromString(varFilterClsid.bstrVal, &clsidFilter);
891                }
892                else if (hr == E_PROP_ID_UNSUPPORTED)
893                {
894                    clsidFilter = GUID_NULL; // No CLSID is listed.
895                    hr = S_OK;
896                }
897            }
898
899            // covert to std::string
900            _bstr_t bstr_t(varName.bstrVal);
901            std::string deviceName(bstr_t);
902            std::string deviceGUID;
903
904            // Add filter name and filename to list
905            if(SUCCEEDED(hr))
906            {
907                LPOLESTR pwszClsid;
908                CHAR  szCLSID[60];
909                hr = StringFromCLSID(clsidFilter, &pwszClsid);
910                if (!FAILED(hr))
911                {
912                    // Convert result to ANSI
913                    WideCharToMultiByte(CP_ACP, 0, pwszClsid, -1, szCLSID, 60, NULL, NULL);
914                    //osg::notify(osg::NOTICE) << "device \"" << truename << "\" id " << szCLSID << std::endl;
915                    deviceGUID = std::string(szCLSID);
916                }
917                CoTaskMemFree(pwszClsid);
918            }
919
920            VariantClear(&varName);
921            VariantClear(&varFilterClsid);
922
923            // Cleanup interfaces
924            if (pPropBag) pPropBag->Release();
925
926            _listDevice.push_back(DeviceEntry(deviceName, deviceGUID, device));
927        }
928    }
929
930   
931};
932
933
934struct ListCapDeviceAvailable
935{
936    typedef std::pair<AM_MEDIA_TYPE*, VIDEOINFOHEADER *> CapEntry;
937    std::vector<CapEntry> _capsList;
938    IAMStreamConfig* _config;
939    ListCapDeviceAvailable(IAMStreamConfig* config) : _config(config)
940    {
941        createList();
942    }
943    ~ListCapDeviceAvailable()
944    {
945        for (int i = 0; i < (int)_capsList.size(); i++)
946            if (_capsList[i].first)
947                DeleteMediaType(_capsList[i].first);
948    }
949
950    void displayCapsFound(const std::string& prefixForMessage = "") const
951    {
952        for (int i = 0; i < (int)_capsList.size(); i++)
953        {
954            VIDEOINFOHEADER* video= _capsList[i].second;
955            displayCap(video, prefixForMessage);
956        }
957    }
958
959    static void displayCap(VIDEOINFOHEADER* video, const std::string& prefix = "")
960    {
961        if (!video)
962            return;
963        double fps = 1.0/ (video->AvgTimePerFrame * 100.0 * 1e-9);
964        FOURCCMap fccMap(video->bmiHeader.biCompression);
965        GUID g1 = (GUID)fccMap;
966        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;
967    }
968
969    std::pair<AM_MEDIA_TYPE*, VIDEOINFOHEADER *> getCaps(int width, int height, double fps)
970    {
971        std::vector<CapEntry> filterResolution;
972        for (int i = 0; i < (int)_capsList.size(); i++)
973        {
974            VIDEOINFOHEADER* video= _capsList[i].second;
975            if (video->bmiHeader.biWidth == width && video->bmiHeader.biHeight == height)
976            {
977                filterResolution.push_back(_capsList[i]);
978            }
979        }
980        // get the max fps if the fps are not reach on the desired resolution
981        typedef std::multimap<double, CapEntry> ContainerFrameRateSorted;
982        ContainerFrameRateSorted filterFrameRate;
983        for (int i = 0; i < (int)filterResolution.size(); i++)
984        {
985            VIDEOINFOHEADER* video= filterResolution[i].second;
986            double capfps = 1.0/  (video->AvgTimePerFrame * 100.0 * 1e-9);
987            double error = fabs(capfps - fps);
988            filterFrameRate.insert(std::pair<double, CapEntry>(error, filterResolution[i]));
989        }
990
991        CapEntry best = CapEntry(0,0);
992        CapEntry first = CapEntry(0,0);
993        for (ContainerFrameRateSorted::iterator it = filterFrameRate.begin();
994               it != filterFrameRate.end();
995               ++it)
996        {
997            if (first == CapEntry(0,0))
998                first = it->second;
999
1000            if (it->first < 1e-3)
1001            {
1002                VIDEOINFOHEADER* video= it->second.second;
1003                FOURCCMap fccMap(video->bmiHeader.biCompression);
1004                GUID g1 = (GUID)fccMap;
1005                if (getStringFromGUID(&g1) == std::string("YUY2"))
1006                    best = it->second;
1007            }
1008        }
1009        if (best != CapEntry(0,0))
1010            return best;
1011        if (first != CapEntry(0,0))
1012            return first;
1013       
1014        if (!_capsList.empty())
1015            return _capsList.front();
1016        return CapEntry(0,0);
1017    }
1018
1019    void createList()
1020    {
1021        std::string device = "capture";
1022        // Use the IPin to get the interface:
1023
1024        // get the number of formats and make sure the strutucre size matches
1025        int iCount, iSize;
1026        VIDEO_STREAM_CONFIG_CAPS caps;
1027        _config->GetNumberOfCapabilities(&iCount, &iSize);
1028        if( sizeof(caps) != iSize )
1029            return;
1030
1031        // now go through all formats and use the one you like
1032        for(int i=0; i < iCount; i++)
1033        {
1034            // GetStreamCaps allocats the AM_MEDIA_TYPE, which must be deleted by using DeleteMediaType
1035            AM_MEDIA_TYPE *pmt = NULL;
1036            if( _config->GetStreamCaps(i, &pmt, (BYTE*)&caps) == S_OK )
1037            {
1038                if (pmt->formattype == FORMAT_VideoInfo && pmt->cbFormat >= sizeof(VIDEOINFOHEADER))
1039                {
1040                    VIDEOINFOHEADER *video=
1041                        reinterpret_cast<VIDEOINFOHEADER*>(pmt->pbFormat);
1042                    _capsList.push_back(CapEntry(pmt, video));
1043                }
1044                else
1045                {
1046                    DeleteMediaType(pmt);
1047                }
1048            }
1049        }
1050    }
1051};
1052
1053
1054bool CTextureRenderer::setupOutputSoundDevice(ICreateDevEnum* devs)
1055{
1056    if (!devs)
1057        return false;
1058
1059    std::string prefixForMessage;
1060    {
1061    std::stringstream ss;
1062    ss << _imageStream.get();
1063    prefixForMessage = ss.str();
1064    }
1065
1066    HRESULT hr;
1067    std::string outputdevice = "Default DirectSound Device";
1068    IEnumMoniker*   audioRenderer = 0; hr = devs?devs->CreateClassEnumerator (CLSID_AudioRendererCategory, &audioRenderer, 0):0; 
1069    if (!checkError(prefixForMessage, hr))
1070        return false;
1071    ListDeviceAvailable deviceFinder(audioRenderer);
1072
1073    deviceFinder.displayDevicesFound(prefixForMessage + " sounddevice", osg::INFO);
1074
1075    ListDeviceAvailable::DeviceEntry device = deviceFinder.getDevice(outputdevice);
1076    if (!device._device)
1077    {
1078        osg::notify(osg::WARN) << prefixForMessage << " no output sound device \"" << outputdevice << "\" found" << std::endl;
1079        return false;
1080    }
1081
1082    _soundOutputDeviceName = device._name;
1083    IMoniker* mon  = device._device;
1084    hr = mon?mon->BindToObject(0,0,IID_IBaseFilter, (void**)&_soundOutputDevice):0;
1085    checkError(prefixForMessage, hr);
1086    if (FAILED(hr))
1087        return false;
1088
1089    hr = _graphBuilder->AddFilter(_soundOutputDevice,NULL);
1090    checkError(prefixForMessage, hr);
1091    if (FAILED(hr))
1092    {
1093        if (_soundOutputDevice) _soundOutputDevice->Release(); _soundOutputDevice = 0;
1094        return false;
1095    }
1096    return true;
1097}
1098
1099bool CTextureRenderer::openVideoCaptureDevice(const std::string& capture, int wantWidth, int wantHeight, double wantFps)
1100{
1101    std::string prefixForMessage;
1102    {
1103    std::stringstream ss;
1104    ss << _imageStream.get();
1105    prefixForMessage = ss.str();
1106    }
1107
1108    HRESULT hr;
1109    ICreateDevEnum* devs = 0; hr = CoCreateInstance (CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC, IID_ICreateDevEnum, (void **) &devs);
1110    if (!checkError(prefixForMessage, hr))
1111        return false;
1112
1113    IEnumMoniker*   cams = 0; hr = devs?devs->CreateClassEnumerator (CLSID_VideoInputDeviceCategory, &cams, 0):0; 
1114    if (!checkError(prefixForMessage, hr))
1115        return false;
1116
1117    ListDeviceAvailable deviceFinder(cams);
1118    {
1119    std::stringstream ss;
1120    ss << std::hex << _imageStream.get() << " capture";
1121    deviceFinder.displayDevicesFound(ss.str(), osg::INFO);
1122    }
1123    ListDeviceAvailable::DeviceEntry device = deviceFinder.getDevice(capture);
1124
1125    if (!device._device)
1126    {
1127        osg::notify(osg::WARN) << _imageStream.get() << " no capture device \"" << capture << "\" found" << std::endl;
1128        return false;
1129    }
1130    _videoCaptureDeviceName = device._name;
1131    osg::notify(osg::NOTICE) << _imageStream.get() << " use capture device \"" << getVideoCaptureDeviceName() << "\"" << std::endl;
1132
1133    {
1134    std::stringstream ss;
1135    ss << _imageStream.get() << " \"" << getVideoCaptureDeviceName() << "\"";
1136    prefixForMessage = ss.str();
1137    }
1138
1139
1140    IMoniker* mon  = device._device;
1141
1142    hr = mon?mon->BindToObject(0,0,IID_IBaseFilter, (void**)&_videoCaptureDevice):0;
1143    if (!checkError(prefixForMessage, hr))
1144        return false;
1145
1146    IEnumPins* pins = 0; hr = _videoCaptureDevice?_videoCaptureDevice->EnumPins(&pins):0;
1147    if (!checkError(prefixForMessage, hr))
1148        return false;
1149
1150    IPin* cap  = 0; hr = pins?pins->Next(1,&cap, 0):0;
1151    if (pins) pins->Release(); pins = 0;
1152    if (!checkError(prefixForMessage, hr))
1153        return false;
1154
1155
1156    IAMStreamConfig* capConfig = 0; hr = cap->QueryInterface( IID_IAMStreamConfig, (void **)&capConfig);
1157    if (capConfig)
1158    {
1159        ListCapDeviceAvailable capsDevice(capConfig);
1160        capsDevice.displayCapsFound(prefixForMessage);
1161        ListCapDeviceAvailable::CapEntry found = capsDevice.getCaps(wantWidth, wantHeight, wantFps);
1162        if (found.first)
1163        {
1164            ListCapDeviceAvailable::displayCap(found.second,  prefixForMessage + " use ");
1165            capConfig->SetFormat(found.first);
1166        }
1167        capConfig->Release();
1168    }
1169
1170    hr = _graphBuilder->AddFilter(_videoCaptureDevice, L"Capture Source");
1171    if (!checkError(prefixForMessage, hr))
1172        return false;
1173
1174    IPin*           rnd  = 0;
1175    hr = FindPin(L"In", &rnd);
1176    if (!checkError(prefixForMessage, hr))
1177        return false;
1178
1179    hr = _graphBuilder->Connect(cap,rnd);
1180
1181    if (rnd) rnd->Release();
1182    if (cap) cap->Release();
1183
1184    bool result = checkError(prefixForMessage, hr);
1185    return result;
1186}
1187
1188
1189bool CTextureRenderer::openSoundCaptureDevice(const std::string& capture, int nbChannels)
1190{
1191    std::string prefixForMessage;
1192    {
1193    std::stringstream ss;
1194    ss << _imageStream.get();
1195    prefixForMessage = ss.str();
1196    }
1197
1198    HRESULT hr;
1199    ICreateDevEnum* devs = 0; hr = CoCreateInstance (CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC, IID_ICreateDevEnum, (void **) &devs);
1200    if (!checkError(prefixForMessage, hr))
1201        return false;
1202
1203    IEnumMoniker*   captureDevices = 0; hr = devs?devs->CreateClassEnumerator (CLSID_AudioInputDeviceCategory, &captureDevices, 0):0; 
1204    if (!checkError(prefixForMessage, hr))
1205        return false;
1206
1207    ListDeviceAvailable deviceFinder(captureDevices);
1208    {
1209    std::stringstream ss;
1210    ss << std::hex << _imageStream.get() << " capture sound ";
1211    deviceFinder.displayDevicesFound(ss.str(), osg::INFO);
1212    }
1213    ListDeviceAvailable::DeviceEntry device = deviceFinder.getDevice(capture);
1214
1215    if (!device._device)
1216    {
1217        osg::notify(osg::WARN) << _imageStream.get() << " no sound capture device \"" << capture << "\" found" << std::endl;
1218        return false;
1219    }
1220    _soundCaptureDeviceName = device._name;
1221    osg::notify(osg::NOTICE) << _imageStream.get() << " use sound capture device \"" << getSoundCaptureDeviceName() << "\"" << std::endl;
1222
1223    {
1224    std::stringstream ss;
1225    ss << _imageStream.get() << " \"" << getSoundCaptureDeviceName() << "\"";
1226    prefixForMessage = ss.str();
1227    }
1228
1229
1230    IMoniker* mon  = device._device;
1231
1232    hr = mon?mon->BindToObject(0,0,IID_IBaseFilter, (void**)&_soundCaptureDevice):0;
1233    if (FAILED(hr))
1234    {
1235        checkError(prefixForMessage, hr);
1236        return false;
1237    }
1238
1239    IAMStreamConfig* pISC = NULL;
1240    hr = FindPinInterface(_soundCaptureDevice, &MEDIATYPE_Audio, PINDIR_OUTPUT, IID_IAMStreamConfig, reinterpret_cast<void**>(&pISC));
1241    if (FAILED(hr))
1242    {
1243        checkError(prefixForMessage, hr);
1244        return false;
1245    }
1246    // loop through all the capabilities (audio formats) and populate the control
1247    int count, size;
1248    hr = pISC->GetNumberOfCapabilities(&count, &size);
1249    if (SUCCEEDED(hr))
1250    {
1251        if (sizeof(AUDIO_STREAM_CONFIG_CAPS) == size)
1252        {
1253            AM_MEDIA_TYPE* pmt = NULL;
1254            AUDIO_STREAM_CONFIG_CAPS ascc;
1255            WAVEFORMATEX* pwfex = NULL;
1256
1257            for (int index=0; index<count; ++index)
1258            {
1259                hr = pISC->GetStreamCaps(index, &pmt, reinterpret_cast<BYTE*>(&ascc));
1260                if (SUCCEEDED(hr))
1261                {
1262                    TCHAR buffer[32];
1263                   
1264                    ZeroMemory(buffer, sizeof(buffer));
1265
1266                    pwfex = (WAVEFORMATEX*)pmt->pbFormat;
1267
1268                    // provide a useful description of the formats
1269                    if (1 == pwfex->nChannels)
1270                    {
1271                        StringCbPrintf(buffer, sizeof(buffer), TEXT("%d channel, %2.1fkHz, %d-bit"), (int)pwfex->nChannels, (float)pwfex->nSamplesPerSec / 1000, (int)pwfex->wBitsPerSample);
1272                    }
1273                    else
1274                    {
1275                        StringCbPrintf(buffer, sizeof(buffer), TEXT("%d channels, %2.1fkHz, %d-bit"), (int)pwfex->nChannels, (float)pwfex->nSamplesPerSec / 1000, (int)pwfex->wBitsPerSample);
1276                    }
1277
1278                    // set default format
1279                    if (pwfex->nChannels == nbChannels)
1280                    {
1281                        pISC->SetFormat(pmt);
1282                        osg::notify(osg::NOTICE) << prefixForMessage << " use format " << buffer << std::endl;
1283                        break;
1284                    } else
1285                        osg::notify(osg::NOTICE) << prefixForMessage << buffer << std::endl;
1286
1287                }
1288            }
1289        }
1290        else
1291        {
1292            osg::notify(osg::WARN) << prefixForMessage << " can t retrieve informations pins" << std::endl;
1293        }
1294    }   
1295    if (pISC) pISC->Release(); pISC = 0;
1296    IPin* captureOutputDevicePinOut = 0; hr = _soundCaptureDevice? ::GetPin(_soundCaptureDevice,L"Capture",&captureOutputDevicePinOut) : 0;
1297    if (FAILED(hr)) {
1298        checkError(prefixForMessage, hr);
1299        return false;
1300    }
1301
1302    hr = _graphBuilder->AddFilter(_soundCaptureDevice, L"Sound Capture Source");
1303    if (FAILED(hr))
1304    {
1305        checkError(prefixForMessage, hr);
1306        return false;
1307    }
1308
1309    if (!setupOutputSoundDevice(devs))
1310    {
1311        devs->Release(); devs = 0;
1312        if (captureOutputDevicePinOut) captureOutputDevicePinOut->Release(); captureOutputDevicePinOut = 0;
1313        return false;
1314    }
1315    devs->Release(); devs = 0;
1316
1317    std::string prefixForMessageSound;
1318    {
1319    std::stringstream ss;
1320    ss << _imageStream.get() << " " << getSoundOutputDeviceName();
1321    prefixForMessageSound = ss.str();
1322    }
1323
1324    IPin* soundOutputDevicePinIn = 0;
1325    hr = _soundOutputDevice->FindPin(L"Audio Input pin (rendered)", &soundOutputDevicePinIn);
1326    if (FAILED(hr))
1327    {
1328        checkError(prefixForMessageSound, hr);
1329        if (soundOutputDevicePinIn)    soundOutputDevicePinIn->Release(); soundOutputDevicePinIn = 0;
1330        if (captureOutputDevicePinOut) captureOutputDevicePinOut->Release(); captureOutputDevicePinOut = 0;
1331        return false;
1332    }
1333
1334    hr = _graphBuilder->Connect(captureOutputDevicePinOut, soundOutputDevicePinIn);
1335
1336    if (soundOutputDevicePinIn)    soundOutputDevicePinIn->Release(); soundOutputDevicePinIn = 0;
1337    if (captureOutputDevicePinOut) captureOutputDevicePinOut->Release(); captureOutputDevicePinOut = 0;
1338
1339    if (FAILED(hr))
1340    {
1341        checkError(prefixForMessageSound, hr);
1342        return false;
1343    }
1344
1345    return true;
1346}
1347
1348
1349bool CTextureRenderer::openCaptureDevices(const DirectShowImageStream::Options& o)
1350{
1351    std::string prefixForMessage;
1352    {
1353    std::stringstream ss;
1354    ss << _imageStream.get();
1355    prefixForMessage = ss.str();
1356    }
1357
1358    DirectShowImageStream::Options options = o;
1359    syncStreams(false);
1360
1361    for (DirectShowImageStream::Options::iterator it = options.begin(); it != options.end(); it++)
1362        osg::notify(osg::NOTICE) << prefixForMessage << " option " << it->first << " = " << it->second << std::endl;
1363
1364    std::string soundCaptureDevice = options["captureSoundDevice"];
1365    std::string videoCaptureDevice = options["captureVideoDevice"];
1366
1367    osg::notify(osg::NOTICE) << prefixForMessage << " try to open video capture device " << videoCaptureDevice;
1368    if (!soundCaptureDevice .empty())
1369        osg::notify(osg::NOTICE) << " and sound capture device " << soundCaptureDevice ;
1370    osg::notify(osg::NOTICE) << std::endl;
1371
1372    if (!initBuildGraph())
1373        return false;
1374
1375    int wantWidth = atoi(options["captureWantedWidth"].c_str());
1376    int wantHeight = atoi(options["captureWantedHeight"].c_str());
1377    float wantFps = atof(options["captureWantedFps"].c_str());
1378    if (!openVideoCaptureDevice(videoCaptureDevice, wantWidth, wantHeight, wantFps))
1379        return false;
1380
1381    if (!soundCaptureDevice.empty() && !openSoundCaptureDevice(soundCaptureDevice ))
1382        osg::notify(osg::WARN) << prefixForMessage << " failed to setup sound capture device " << soundCaptureDevice  << std::endl;
1383
1384    return true;
1385}
1386
1387
1388bool CTextureRenderer::openFile(const std::string& file)
1389{
1390    syncStreams(true);
1391    WCHAR wFileName[MAX_PATH];
1392    wFileName[MAX_PATH-1] = 0;    // NULL-terminate
1393    if (file.empty())
1394        return false;
1395
1396    _filename = file;
1397    std::string prefixForMessage;
1398    {
1399    std::stringstream ss;
1400    ss << _imageStream.get() << " " << getFilename();
1401    prefixForMessage = ss.str();
1402    }
1403
1404    const char *ansistr = file.c_str();
1405    int lenA = lstrlenA(ansistr);
1406    int lenW;
1407    BSTR unicodestr = 0;
1408
1409    lenW = ::MultiByteToWideChar(CP_ACP, 0, ansistr, lenA, 0, 0);
1410    if (lenW > 0)
1411    {
1412      // Check whether conversion was successful
1413      unicodestr = ::SysAllocStringLen(0, lenW);
1414      ::MultiByteToWideChar(CP_ACP, 0, ansistr, lenA, unicodestr, lenW);
1415    }
1416
1417    if (unicodestr!=0)
1418    {
1419        (void)StringCchCopyW(wFileName, NUMELMS(wFileName), unicodestr);
1420
1421        // when done, free the BSTR
1422        ::SysFreeString(unicodestr);
1423    }
1424
1425    HRESULT hr;
1426    if (!initBuildGraph())
1427        return false;
1428
1429    IPin* videoOutputPin = 0;
1430
1431    std::string lowercase = file;
1432    std::transform(lowercase.begin(), lowercase.end(), lowercase.begin(), tolower);
1433    if (lowercase.rfind(".wmv") != std::string::npos)
1434    {
1435        hr = _graphBuilder->AddSourceFilter(wFileName, L"Windows Media source filter", &_fileSource);
1436        if (!checkError(prefixForMessage, hr))
1437            return false;
1438        hr = _fileSource?_fileSource->FindPin(L"Raw Video 1", &videoOutputPin):0;
1439    }
1440    else
1441    {
1442        hr = _graphBuilder->AddSourceFilter(wFileName, L"File Source", &_fileSource);
1443        if (!checkError(prefixForMessage, hr))
1444            return false;
1445        hr = _fileSource?_fileSource->FindPin(L"Output", &videoOutputPin):0;
1446    }
1447
1448    if (!checkError(prefixForMessage, hr))
1449        return false;
1450
1451    IPin*           rnd  = 0;
1452    hr = FindPin(L"In", &rnd);
1453    if (!checkError(prefixForMessage, hr))
1454        return false;
1455
1456    hr = _graphBuilder->Connect(videoOutputPin, rnd);
1457    if (videoOutputPin) videoOutputPin->Release(); videoOutputPin = 0;
1458
1459    if (rnd) rnd->Release(); rnd = 0;
1460    if (!checkError(prefixForMessage, hr))
1461        return false;
1462
1463
1464    if (lowercase.rfind(".avi") == std::string::npos) // not an avi, dont try to connect sounds
1465        return true;
1466
1467    // check if we find the sounds output pin on the streams
1468    IBaseFilter* AVISpliterFilter = 0;
1469    hr = _graphBuilder->FindFilterByName(L"AVI Splitter", &AVISpliterFilter);
1470    if (FAILED(hr))
1471        osg::notify(osg::WARN) << prefixForMessage << " did not find AVI SPlitter to connect sound, " << getErrorMessage(hr) << std::endl;
1472
1473    if (AVISpliterFilter)
1474    {
1475        IPin* soundStreamPinOut = 0;
1476        hr = AVISpliterFilter->FindPin(L"Stream 01",&soundStreamPinOut);
1477        AVISpliterFilter->Release(); AVISpliterFilter = 0;
1478
1479        if (FAILED(hr))
1480            osg::notify(osg::WARN) << prefixForMessage << " can't find Stream 01 pin on AVIS Splitter, maybe the flux does have sound, " << getErrorMessage(hr) << std::endl;
1481
1482        if (soundStreamPinOut)
1483        {
1484            // connect sounds to graph
1485            ICreateDevEnum* devs = 0; hr = CoCreateInstance (CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC, IID_ICreateDevEnum, (void **) &devs);
1486            checkError(prefixForMessage, hr);
1487            if (devs && setupOutputSoundDevice(devs))
1488            {
1489                devs->Release(); devs = 0;
1490                std::string prefixForMessageSound;
1491                {
1492                std::stringstream ss;
1493                ss << _imageStream.get() << " " << getSoundOutputDeviceName();
1494                prefixForMessageSound = ss.str();
1495                }
1496
1497                IPin* soundOutputDevicePinIn = 0;
1498                hr = _soundOutputDevice->FindPin(L"Audio Input pin (rendered)", &soundOutputDevicePinIn);
1499                checkError(prefixForMessageSound, hr);
1500
1501                hr = _graphBuilder->Connect(soundStreamPinOut, soundOutputDevicePinIn);
1502
1503                if (soundOutputDevicePinIn)    soundOutputDevicePinIn->Release(); soundOutputDevicePinIn = 0;
1504                if (soundStreamPinOut) soundStreamPinOut->Release(); soundStreamPinOut = 0;
1505
1506                if (!checkError(prefixForMessageSound, hr) && _soundOutputDevice)
1507                {
1508                    _graphBuilder->RemoveFilter(_soundOutputDevice);
1509                    _soundOutputDevice->Release(); _soundOutputDevice = 0;
1510                }
1511            }
1512        }
1513    }
1514
1515    return true;
1516}
1517
1518
1519
1520//-----------------------------------------------------------------------------
1521// CleanupDShow
1522//-----------------------------------------------------------------------------
1523void CTextureRenderer::releaseRessources()
1524{
1525    // Shut down the graph
1526    if (_mediaControl) _mediaControl->Stop();
1527    _imageStream = 0;
1528
1529    if (_mediaControl) _mediaControl->Release(); _mediaControl = 0;
1530    if (_mediaEvent) _mediaEvent->Release(); _mediaEvent = 0;
1531    if (_mediaSeeking) _mediaSeeking->Release(); _mediaSeeking = 0;
1532    // remove filter outside because this is a filter too.
1533}
1534
1535
1536//-----------------------------------------------------------------------------
1537// CTextureRenderer constructor
1538//-----------------------------------------------------------------------------
1539
1540CTextureRenderer::CTextureRenderer( DirectShowImageStream* is, HRESULT* valid)
1541    : CBaseVideoRenderer(__uuidof(CLSID_TextureRenderer),
1542                         NAME("Texture Renderer"),
1543                         NULL,
1544                         valid)
1545{
1546    std::string prefixForMessage;
1547    {
1548    std::stringstream ss;
1549    ss << is;
1550    prefixForMessage = ss.str();
1551    }
1552
1553    if (FAILED(*valid))
1554        checkError(prefixForMessage, *valid);
1555
1556    _imageStream = is;
1557    _fileSource = 0;
1558    _mediaControl = 0;
1559    _mediaEvent = 0;
1560    _mediaSeeking = 0;
1561    _graphBuilder = 0;
1562    _videoCaptureDevice = 0;
1563    _soundOutputDevice = 0;
1564    _soundCaptureDevice = 0;
1565}
1566
1567
1568//-----------------------------------------------------------------------------
1569// CTextureRenderer destructor
1570//-----------------------------------------------------------------------------
1571CTextureRenderer::~CTextureRenderer()
1572{
1573}
1574
1575
1576//-----------------------------------------------------------------------------
1577// CheckMediaType: This method forces the graph to give us an R8G8B8 video
1578// type, making our copy to texture memory trivial.
1579//-----------------------------------------------------------------------------
1580HRESULT CTextureRenderer::CheckMediaType(const CMediaType *pmt)
1581{
1582    HRESULT   hr = E_FAIL;
1583    VIDEOINFO *pvi=0;
1584
1585    CheckPointer(pmt,E_POINTER);
1586
1587    // Reject the connection if this is not a video type
1588    if( *pmt->FormatType() != FORMAT_VideoInfo ) {
1589        return E_INVALIDARG;
1590    }
1591
1592    // Only accept RGB24 video
1593    pvi = (VIDEOINFO *)pmt->Format();
1594
1595    if (!IsEqualGUID( *pmt->Type(),    MEDIATYPE_Video))
1596        osg::notify(osg::WARN) << _imageStream.get() << " media type not a video format" << std::endl;
1597
1598
1599    if( IsEqualGUID( *pmt->Subtype(), MEDIASUBTYPE_RGB24))
1600    {
1601        osg::notify(osg::NOTICE) << _imageStream.get() << " Texture Renderer use media " << getStringFromGUID(pmt->Subtype()) << std::endl;
1602        hr = S_OK;
1603    }
1604    else
1605    {
1606        osg::notify(osg::INFO) << _imageStream.get() << " Texture Renderer check media " << getStringFromGUID(pmt->Subtype()) << std::endl;
1607    }
1608
1609    return hr;
1610}
1611
1612//-----------------------------------------------------------------------------
1613// SetMediaType: Graph connection has been made.
1614//-----------------------------------------------------------------------------
1615HRESULT CTextureRenderer::SetMediaType(const CMediaType *pmt)
1616{
1617    // Retrive the size of this media type
1618    VIDEOINFO *pviBmp;                      // Bitmap info header
1619    pviBmp = (VIDEOINFO *)pmt->Format();
1620
1621    _width  = pviBmp->bmiHeader.biWidth;
1622    _height = abs(pviBmp->bmiHeader.biHeight);
1623    _pitch  = (_width * 3 + 3) & ~(3); // We are forcing RGB24
1624    _imageStream->setImage(_width, _height, 1, GL_RGB, GL_BGR, GL_UNSIGNED_BYTE, 0, osg::Image::NO_DELETE);
1625    return S_OK;
1626}
1627
1628//-----------------------------------------------------------------------------
1629// DoRenderSample: A sample has been delivered. Copy it to the texture.
1630//-----------------------------------------------------------------------------
1631HRESULT CTextureRenderer::DoRenderSample( IMediaSample * pSample )
1632{
1633    BYTE  *pBmpBuffer; // Bitmap buffer, texture buffer
1634    CheckPointer(pSample,E_POINTER);
1635
1636    // Get the video bitmap buffer
1637    pSample->GetPointer( &pBmpBuffer );
1638    if (_imageStream.valid())
1639        _imageStream->setImage(_width, _height, 1, GL_RGB, GL_BGR, GL_UNSIGNED_BYTE, pBmpBuffer, osg::Image::NO_DELETE);
1640    return S_OK;
1641}
1642
1643void CTextureRenderer::syncStreams(bool state)
1644{
1645    if (state == true)
1646        _dropFrame = !S_OK;
1647    else
1648        _dropFrame = S_OK;
1649}
1650HRESULT CTextureRenderer::ShouldDrawSampleNow(IMediaSample *sample, REFERENCE_TIME *start, REFERENCE_TIME *stop) {
1651    return _dropFrame; // disable droping of frames
1652}
1653
1654bool CTextureRenderer::StopFilters()
1655{
1656    HRESULT hr;
1657    if (_mediaControl)
1658    {
1659        hr = _mediaControl->Stop();
1660        if (FAILED(hr))
1661        {
1662            osg::notify(osg::WARN) << _imageStream.get() << " " << getErrorMessage(hr) << std::endl;
1663            return false;
1664        }
1665    }
1666    return true;
1667}
1668
1669DirectShowImageStream::DirectShowImageStream()
1670{
1671    _options["captureWantedWidth"] = "1920";
1672    _options["captureWantedHeight"] = "1080";
1673    _options["captureWantedFps"] = "30";
1674
1675    HRESULT hr = CoInitialize (NULL);
1676    if (FAILED(hr))
1677    {
1678        osg::notify(osg::WARN) << this << " error in constructor " << getErrorMessage(hr) << std::endl;
1679    }
1680
1681}
1682DirectShowImageStream::DirectShowImageStream(const DirectShowImageStream& d,const osg::CopyOp& c) : osg::ImageStream(d, c)
1683{
1684    // i guess it's invalid
1685}
1686
1687DirectShowImageStream::~DirectShowImageStream()
1688{
1689    stop();
1690    CoUninitialize();
1691}
1692
1693bool DirectShowImageStream::openFile(const std::string& file)
1694{
1695    HRESULT valid = S_OK;
1696    _renderer = new CTextureRenderer(this, &valid);
1697    if (FAILED(valid))
1698    {
1699        return false;
1700    }
1701    if (!_renderer->openFile(file))
1702    {
1703        return false;
1704    }
1705    return true;
1706}
1707
1708bool DirectShowImageStream::openCaptureDevices()
1709{
1710    HRESULT valid = S_OK;
1711    _renderer = new CTextureRenderer(this, &valid);
1712    if (FAILED(valid))
1713    {
1714        return false;
1715    }
1716    if (!_renderer->openCaptureDevices(_options))
1717    {
1718        return false;
1719    }
1720   
1721    return true;
1722}
1723
1724
1725
1726void DirectShowImageStream::play()
1727{
1728    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
1729    if (_status == PLAYING)
1730        return;
1731
1732    if (_renderer.valid() && _renderer->_mediaControl)
1733    {
1734        HRESULT hr;
1735        hr = _renderer->_mediaControl->Run();
1736        // Start the graph running;
1737        if (FAILED(hr))
1738        {
1739            osg::notify(osg::WARN) << this << " can't run the graph " <<  getErrorMessage(hr) <<  std::endl;
1740        }
1741        else
1742        {
1743            _status = PLAYING;
1744        }
1745    }
1746}
1747
1748void DirectShowImageStream::pause()
1749{
1750    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
1751    if (_status == PAUSED)
1752        return;
1753
1754    if (_renderer.valid() && _renderer->_mediaControl)
1755    {
1756        HRESULT hr;
1757        hr = _renderer->_mediaControl->Pause();
1758        if (FAILED(hr))
1759        {
1760            osg::notify(osg::NOTICE) << this << " " << getErrorMessage(hr) << std::endl;
1761        }
1762        else
1763        {
1764            _status = PAUSED;
1765        }
1766    }
1767}
1768
1769void DirectShowImageStream::rewind()
1770{
1771    seek(0);
1772}
1773
1774osg::ImageStream::StreamStatus DirectShowImageStream::getStatus()
1775{
1776    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
1777    return _status;
1778}
1779
1780void DirectShowImageStream::seek(double time)
1781{
1782    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
1783    if (_renderer.valid() && _renderer->_mediaSeeking)
1784    {
1785        double start = time / (100 * 1e-9);
1786        LONGLONG start2 = static_cast<LONGLONG>(start);
1787        HRESULT hr = _renderer->_mediaSeeking->SetPositions(&start2,AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
1788        if (FAILED(hr))
1789        {
1790            osg::notify(osg::NOTICE) << this << " " << getErrorMessage(hr) << std::endl;
1791        }
1792    }
1793
1794}
1795void DirectShowImageStream::setOptions(const Options& map)
1796{
1797    for (Options::const_iterator it = map.begin(); it != map.end(); it++)
1798        _options[it->first] = it->second;
1799}
1800
1801void DirectShowImageStream::quit(bool waitForThreadToExit)
1802{
1803    stop();
1804}
1805
1806double DirectShowImageStream::getLength() const 
1807{
1808    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
1809    double duration = 0;
1810    if (_renderer.valid() && _renderer->_mediaSeeking)
1811    {
1812        LONGLONG d = 0;
1813        _renderer->_mediaSeeking->GetDuration(&d);
1814        duration = static_cast<double>(d);
1815        duration = duration * (100.0 * 1e-9); // default unit in directshow IMediaSeeking
1816    }
1817    return duration;
1818}
1819
1820double DirectShowImageStream::getFrameRate() const 
1821{
1822    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
1823    int frameRate = 0;
1824    if (_renderer.valid())
1825        _renderer->get_AvgFrameRate(&frameRate);
1826    return static_cast<double>(frameRate) * 1e-2;
1827}
1828
1829void DirectShowImageStream::setTimeMultiplier(double rate)
1830{
1831    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
1832    if (_renderer.valid() && _renderer->_mediaSeeking)
1833        _renderer->_mediaSeeking->SetRate(rate);
1834}
1835
1836double DirectShowImageStream::getTimeMultiplier() const 
1837{
1838    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
1839    double rate = 1.0;
1840    if (_renderer.valid() && _renderer->_mediaSeeking)
1841        _renderer->_mediaSeeking->GetRate(&rate);
1842    return rate;
1843}
1844
1845void DirectShowImageStream::stop()
1846{
1847    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
1848    if (!_renderer.valid())
1849        return;
1850    if (!_renderer->StopFilters())
1851        osg::notify(osg::WARN) << this << " cant stop filters" << std::endl;
1852
1853    _renderer->releaseRessources();
1854    // Enumerate the filters in the graph.
1855    IEnumFilters *pEnum = NULL;
1856    IGraphBuilder* gb = _renderer->getGraphBuilder();
1857    if (!gb)
1858        return;
1859    HRESULT hr = gb->EnumFilters(&pEnum);
1860    if (SUCCEEDED(hr))
1861    {
1862        IBaseFilter *pFilter = NULL;
1863        while (S_OK == pEnum->Next(1, &pFilter, NULL))
1864         {
1865             // Remove the filter.
1866             gb->RemoveFilter(pFilter);
1867             // Reset the enumerator.
1868             pEnum->Reset();
1869             pFilter->Release();
1870        }
1871        pEnum->Release();
1872    }
1873    if (gb) gb->Release(); gb = 0;
1874    _renderer = 0;
1875}
Note: See TracBrowser for help on using the browser.