/* -*-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 */ #include "DirectShowTexture" #include #include #include #include #include #include #include #include #include #include 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")}, {&ROPSETID_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 _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 CapEntry; std::vector _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 getCaps(int width, int height, double fps) { std::vector 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 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(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(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(&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; indexGetStreamCaps(index, &pmt, reinterpret_cast(&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 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 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 lock(_mutex); return _status; } void DirectShowImageStream::seek(double time) { OpenThreads::ScopedLock lock(_mutex); if (_renderer.valid() && _renderer->_mediaSeeking) { double start = time / (100 * 1e-9); LONGLONG start2 = static_cast(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 lock(_mutex); double duration = 0; if (_renderer.valid() && _renderer->_mediaSeeking) { LONGLONG d = 0; _renderer->_mediaSeeking->GetDuration(&d); duration = static_cast(d); duration = duration * (100.0 * 1e-9); // default unit in directshow IMediaSeeking } return duration; } double DirectShowImageStream::getFrameRate() const { OpenThreads::ScopedLock lock(_mutex); int frameRate = 0; if (_renderer.valid()) _renderer->get_AvgFrameRate(&frameRate); return static_cast(frameRate) * 1e-2; } void DirectShowImageStream::setTimeMultiplier(double rate) { OpenThreads::ScopedLock lock(_mutex); if (_renderer.valid() && _renderer->_mediaSeeking) _renderer->_mediaSeeking->SetRate(rate); } double DirectShowImageStream::getTimeMultiplier() const { OpenThreads::ScopedLock lock(_mutex); double rate = 1.0; if (_renderer.valid() && _renderer->_mediaSeeking) _renderer->_mediaSeeking->GetRate(&rate); return rate; } void DirectShowImageStream::stop() { OpenThreads::ScopedLock 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; }