Main Page | Class Hierarchy | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages | Examples

vetDirectXInput2.cpp

00001 //------------------------------------------------------------------------------
00002 // File: AMCap.cpp
00003 //
00004 // Desc: Audio/Video Capture sample for DirectShow
00005 //UpdateStatus
00006 //
00007 // Copyright (c) Microsoft Corporation.  All rights reserved.
00008 //------------------------------------------------------------------------------
00009 
00010 
00011 
00012 //#define _WIN32_DCOM // needed by VC6 for OLE..
00013 
00014 
00015 #include <streams.h>
00016 
00017 
00018 #include <windows.h>
00019 
00020 #include <dbt.h>
00021 #include <mmreg.h>
00022 #include <msacm.h>
00023 
00024 //#include <dshow.h>
00025 #include <Qedit.h>
00026 
00027 #include <fcntl.h>
00028 #include <io.h>
00029 #include <stdio.h>
00030 #include <commdlg.h>
00031 #include <atlbase.h>
00032 
00038 //#include "StdAfx.h"
00039 // stdafx.h : include file for standard system include files,
00040 //      or project specific include files that are used frequently,
00041 //      but are changed infrequently
00042 
00043 #if !defined(AFX_STDAFX_H__08E7CDC6_7F58_11D2_8CF1_00A0C9441E20__INCLUDED_)
00044 #define AFX_STDAFX_H__08E7CDC6_7F58_11D2_8CF1_00A0C9441E20__INCLUDED_
00045 
00046 #if _MSC_VER > 1000
00047 #pragma once
00048 #endif // _MSC_VER > 1000
00049 
00050 #ifdef WIN32_LEAN_AND_MEAN
00051 #undef WIN32_LEAN_AND_MEAN
00052 #endif
00053 
00054 #define _ATL_APARTMENT_THREADED
00055 #define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
00056 
00057 #include <atlbase.h>
00058 extern CComModule _Module;
00059 #include <atlcom.h>
00060 
00061 //{{AFX_INSERT_LOCATION}}
00062 // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
00063 
00064 #endif // !defined(AFX_STDAFX_H__08E7CDC6_7F58_11D2_8CF1_00A0C9441E20__INCLUDED)
00065 
00070 
00071 // device notification definitions
00072 #if (WINVER < 0x0500)
00073 
00074 #define DBT_DEVTYP_DEVICEINTERFACE      0x00000005  // device interface class
00075 #define DEVICE_NOTIFY_WINDOW_HANDLE     0x00000000
00076 
00077 typedef PVOID   HDEVNOTIFY;
00078 
00079 #endif
00080 
00081 extern "C"
00082 {
00083     typedef BOOL (/* WINUSERAPI */ WINAPI *PUnregisterDeviceNotification)(
00084         IN HDEVNOTIFY Handle
00085         );
00086 
00087     typedef HDEVNOTIFY (/* WINUSERAPI */ WINAPI *PRegisterDeviceNotificationA)(
00088         IN HANDLE hRecipient,
00089         IN LPVOID NotificationFilter,
00090         IN DWORD Flags
00091         );
00092 
00093     typedef HDEVNOTIFY (/* WINUSERAPI */ WINAPI *PRegisterDeviceNotificationW)(
00094         IN HANDLE hRecipient,
00095         IN LPVOID NotificationFilter,
00096         IN DWORD Flags
00097         );
00098 }
00099 
00100 #ifdef UNICODE
00101 #define PRegisterDeviceNotification  PRegisterDeviceNotificationW
00102 #else
00103 #define PRegisterDeviceNotification  PRegisterDeviceNotificationA
00104 #endif // !UNICODE
00105 
00106 #if (WINVER < 0x0500)
00107 
00108 typedef struct _DEV_BROADCAST_DEVICEINTERFACE_A {
00109     DWORD       dbcc_size;
00110     DWORD       dbcc_devicetype;
00111     DWORD       dbcc_reserved;
00112     GUID        dbcc_classguid;
00113     char        dbcc_name[1];
00114 } DEV_BROADCAST_DEVICEINTERFACE_A, *PDEV_BROADCAST_DEVICEINTERFACE_A;
00115 
00116 typedef struct _DEV_BROADCAST_DEVICEINTERFACE_W {
00117     DWORD       dbcc_size;
00118     DWORD       dbcc_devicetype;
00119     DWORD       dbcc_reserved;
00120     GUID        dbcc_classguid;
00121     wchar_t     dbcc_name[1];
00122 } DEV_BROADCAST_DEVICEINTERFACE_W, *PDEV_BROADCAST_DEVICEINTERFACE_W;
00123 
00124 #ifdef UNICODE
00125 typedef DEV_BROADCAST_DEVICEINTERFACE_W   DEV_BROADCAST_DEVICEINTERFACE;
00126 typedef PDEV_BROADCAST_DEVICEINTERFACE_W  PDEV_BROADCAST_DEVICEINTERFACE;
00127 #else
00128 typedef DEV_BROADCAST_DEVICEINTERFACE_A   DEV_BROADCAST_DEVICEINTERFACE;
00129 typedef PDEV_BROADCAST_DEVICEINTERFACE_A  PDEV_BROADCAST_DEVICEINTERFACE;
00130 #endif // UNICODE
00131 #endif // WINVER
00132 
00133 
00134 // window messages
00135 #define WM_FGNOTIFY WM_USER+1
00136 
00137 
00138 #include "vetDirectXInput2.h"
00139 
00140 //#include "status.h"
00141 //#include "crossbar.h"
00151 //include "SampleCGB.h"
00152 //------------------------------------------------------------------------------
00153 // File: SampleCGB.h
00154 //
00155 // Desc: DirectShow sample code - definition of sample capture graph builder
00156 //
00157 // Copyright (c) Microsoft Corporation.  All rights reserved.
00158 //------------------------------------------------------------------------------
00159 #include <ks.h>
00160 
00161 #ifndef KSCATEGORY_ENCODER
00162 #define STATIC_KSCATEGORY_ENCODER\
00163     0x19689bf6, 0xc384, 0x48fd, 0xad, 0x51, 0x90, 0xe5, 0x8c, 0x79, 0xf7, 0xb
00164 DEFINE_GUIDSTRUCT("19689BF6-C384-48fd-AD51-90E58C79F70B", KSCATEGORY_ENCODER);
00165 #define KSCATEGORY_ENCODER DEFINE_GUIDNAMED(KSCATEGORY_ENCODER)
00166 #endif
00167 
00168 #ifndef KSCATEGORY_MULTIPLEXER
00169 #define STATIC_KSCATEGORY_MULTIPLEXER\
00170     0x236C9559, 0xADCE, 0x4736, 0xBF, 0x72, 0xBA, 0xB3, 0x4E, 0x39, 0x21, 0x96
00171 DEFINE_GUIDSTRUCT("236C9559-ADCE-4736-BF72-BAB34E392196", KSCATEGORY_MULTIPLEXER);
00172 #define KSCATEGORY_MULTIPLEXER DEFINE_GUIDNAMED(KSCATEGORY_MULTIPLEXER)
00173 #endif
00174 
00175 #ifndef MEDIASUBTYPE_Mpeg2
00176 #define STATIC_MEDIASUBTYPE_Mpeg2\
00177     0x7DC2C665, 0x4033, 0x4CAF, 0x92, 0x73, 0xF7, 0xD7, 0x97, 0xFB, 0x24, 0x5C
00178 DEFINE_GUIDSTRUCT("7DC2C665-4033-4CAF-9273-F7D797FB245C", MEDIASUBTYPE_Mpeg2);
00179 #define MEDIASUBTYPE_Mpeg2 DEFINE_GUIDNAMED(MEDIASUBTYPE_Mpeg2)
00180 #endif
00181 
00182 #ifndef CLSID_Dump
00183 #define STATIC_CLSID_Dump\
00184     0x36a5f770, 0xfe4c, 0x11ce, 0xa8, 0xed, 0x00, 0xaa, 0x00, 0x2f, 0xea, 0xb5
00185 DEFINE_GUIDSTRUCT("36a5f770-fe4c-11ce-a8ed-00aa002feab5", CLSID_Dump);
00186 #define CLSID_Dump DEFINE_GUIDNAMED(CLSID_Dump)
00187 #endif
00188 
00189 
00190 
00191 class ISampleCaptureGraphBuilder
00192 {
00193 public:
00194 
00195 public:
00196     ISampleCaptureGraphBuilder()
00197     {
00198         AudPID_ = 0xC0;
00199         VidPID_ = 0xE0;
00200         HRESULT hr = graphBuilder2_.CoCreateInstance( CLSID_CaptureGraphBuilder2 );
00201         ASSERT( S_OK == hr );
00202     }
00203 
00204     //
00205     //  OnFinalConstruct build the ICaptureGraphBuilder2
00206     //
00207     void ReleaseFilters( )
00208     {
00209         pMultiplexer_.Release();
00210         pEncoder_.Release();
00211         pMPEG2Demux_.Release();
00212         pMediaControl_.Release();
00213         pAudioPin_.Release();
00214         pVideoPin_.Release();
00215 
00216     }
00217 
00218 public:
00219 
00220     STDMETHOD(AllocCapFile)( LPCOLESTR lpwstr, DWORDLONG dwlSize );
00221 
00222     STDMETHOD(ControlStream)( const GUID *pCategory,
00223                           const GUID *pType,
00224                           IBaseFilter *pFilter,
00225                           REFERENCE_TIME *pstart,
00226                           REFERENCE_TIME *pstop,
00227                           WORD wStartCookie,
00228                           WORD wStopCookie
00229                           );
00230 
00231     STDMETHOD(CopyCaptureFile)(  LPOLESTR lpwstrOld,
00232                               LPOLESTR lpwstrNew,
00233                               int fAllowEscAbort,
00234                               IAMCopyCaptureFileProgress *pCallback
00235                               );
00236 
00237     STDMETHOD(FindInterface)(const GUID *pCategory,
00238                           const GUID *pType,
00239                           IBaseFilter *pf,
00240                           REFIID riid,
00241                           void **ppint
00242                           );
00243 
00244     STDMETHOD(FindPin)( IUnknown *pSource,
00245                       PIN_DIRECTION pindir,
00246                       const GUID *pCategory,
00247                       const GUID *pType,
00248                       BOOL fUnconnected,
00249                       int num,
00250                       IPin **ppPin
00251                       );
00252 
00253 
00254     STDMETHOD(GetFiltergraph)( IGraphBuilder **ppfg );
00255 
00256     STDMETHOD(RenderStream)( const GUID *pCategory,
00257                           const GUID *pType,
00258                           IUnknown *pSource,
00259                           IBaseFilter *pIntermediate,
00260                           IBaseFilter *pSink
00261                           );
00262 
00263 
00264     STDMETHOD(SetFiltergraph)( IGraphBuilder *pfg );
00265 
00266 
00267     STDMETHOD(SetOutputFileName)(
00268                                 const GUID *pType,
00269                                 LPCOLESTR lpwstrFile,
00270                                 IBaseFilter **ppf,
00271                                 IFileSinkFilter **pSink
00272                                 );
00273 
00274 
00275 protected:
00276 
00277     HRESULT CreateVideoPin( CComPtr<IMpeg2Demultiplexer> pIMpeg2Demux );
00278     HRESULT CreateAudioPin( CComPtr<IMpeg2Demultiplexer> pIMpeg2Demux );
00279 
00280 
00281     HRESULT ConfigureMPEG2Demux( CComPtr<IBaseFilter> pFilter);
00282 
00283     HRESULT FindMPEG2Pin( CComPtr<IBaseFilter> pFilter, CComPtr<IPin>& pPin );
00284     HRESULT FindPin(
00285                 CComPtr<IBaseFilter> pFilter,
00286                 const REGPINMEDIUM& regPinMedium,
00287                 PIN_DIRECTION direction,
00288                 BOOL video,
00289                 CComPtr<IPin>& pPin);
00290 
00291     HRESULT GetMedium( CComPtr<IPin> pPin, REGPINMEDIUM& regPinMedium );
00292     HRESULT AddMPEG2Demux( );
00293 
00294     HRESULT FindEncoder( CComPtr<IEnumMoniker> pEncoders, REGPINMEDIUM pinMedium,
00295                          CComPtr<IBaseFilter>& pEncoder );
00296 
00297     BOOL IsMPEG2Pin( CComPtr<IPin> pPin );
00298     BOOL IsVideoPin( CComPtr<IPin> pPin );
00299     BOOL IsAudioPin( CComPtr<IPin> pPin );
00300 
00301     BOOL HasMediaType( CComPtr<IPin> pPin, REFGUID majorType );
00302 
00303     HRESULT FindAudioPin( CComPtr<IBaseFilter> pFilter, CComPtr<IPin>& pPin  );
00304     HRESULT FindVideoPin( CComPtr<IBaseFilter> pFilter, CComPtr<IPin>& pPin  );
00305 
00306     //
00307     //  tries to build MPEG2 segment for pFilter capture filter
00308     //
00309     HRESULT BuildMPEG2Segment( CComPtr<IBaseFilter> pFilter );
00310     //
00311     //  renders pPin to a MPEG2 demux
00312     //
00313     HRESULT RenderToMPEG2Demux( CComPtr<IPin> pPin );
00314     //
00315     //  renders pin pPin with pinMedium to an encoder
00316     //
00317     HRESULT RenderToMPEG2Demux( CComPtr<IPin> pPin, const REGPINMEDIUM& pinMedium,
00318                                 CComPtr<IEnumMoniker> pEncoders );
00319     //
00320     //  renders pPin to a MPEG2 demux; there is no special medium, the encoder will be
00321     //  serched in the encoder category
00322     //
00323     HRESULT RenderToMPEG2Demux( CComPtr<IPin> pPin, CComPtr<IEnumMoniker> pEncoders  );
00324     //
00325     //  renders the encoder to a MPEG2 demux
00326     //
00327     HRESULT ConnectEncoderToMPEG2Demux( CComPtr< IBaseFilter > pEncoder,
00328                                         const REGPINMEDIUM& pinMedium );
00329     //
00330     //  renders the demux to a MPEG2 demux
00331     //
00332     HRESULT ConnectMultiplexerToMPEG2Demux( CComPtr<IBaseFilter> pEncoder,
00333                                             CComPtr< IEnumMoniker > pMultiplexers );
00334   public:
00335         //
00336     //  helper methods; connects a pin to a filter and a filter to another one
00337     //
00338     HRESULT ConnectPin( CComPtr<IPin>, CComPtr< IBaseFilter > );
00339 
00340 
00341     HRESULT ConnectFilters(CComPtr<IBaseFilter> pUpFilter,
00342                            CComPtr<IBaseFilter> pDownFilter);
00343 protected:
00344     //
00345     //  for audio pin; the multiplexer has already beem chosen
00346     //  if there is no encoder, the method fails
00347     //
00348     HRESULT ConnectAudioPinToMultiplexer( CComPtr<IPin> pPin,
00349                                           CComPtr<IBaseFilter> pMultiplexer);
00350 
00351 
00352     //
00353     //  helper methods - get the encoders using SystemDeviceEnum or IFilterMapper2
00354     //
00355     HRESULT GetEncodersByCategory( CComPtr<IEnumMoniker>& pEncoders );
00356     HRESULT GetEncodersByEnumerating( CComPtr<IPin> pPin, const REGPINMEDIUM& pinMedium,
00357                                       CComPtr<IEnumMoniker>& pEncoders );
00358 
00359     //
00360     //  helper methods - get the multiplexers using SystemDeviceEnum or IFilterMapper2
00361     //
00362     HRESULT GetMultiplexersByCategory( CComPtr<IEnumMoniker>& pMultiplexers);
00363     HRESULT GetMultiplexersByFilterMapper( CComPtr<IEnumMoniker>& pMultiplexers,
00364                                            const REGPINMEDIUM& pinMedium );
00365 
00366     CComPtr<IBaseFilter> pMultiplexer_;
00367     CComPtr<IBaseFilter> pEncoder_;
00368     CComPtr<IBaseFilter> pMPEG2Demux_;
00369 
00370 protected:
00371 
00372     CComPtr<ICaptureGraphBuilder2> graphBuilder2_;
00373     CComPtr<IGraphBuilder> graph_;
00374     CComPtr<IMediaControl> pMediaControl_;
00375 
00376     ULONG   VidPID_,
00377             AudPID_;
00378 
00379 private:
00380     CComPtr<IPin>   pAudioPin_;
00381     CComPtr<IPin>   pVideoPin_;
00382 
00383 };
00384 
00385 
00386 
00387 //------------------------------------------------------------------------------
00388 // File: SampleCGB.cpp
00389 //
00390 // Desc: DirectShow sample code - Sample capture graph builder class
00391 //
00392 // Copyright (c) Microsoft Corporation.  All rights reserved.
00393 //------------------------------------------------------------------------------
00394 
00395 
00396 //#include <streams.h>
00397 //#include "ks.h"
00398 #include "ksproxy.h"
00399 //#include <atlbase.h>
00400 //#include  "SampleCGB.h"
00401 
00402 
00403 //
00404 //  ISampleCaptureGraphBuilder is trying to connect the video pin to the MPEG2 demux.
00405 //  The possible configurations are:
00406 //
00407 //
00408 //
00409 // 1. capture filter- > audio / video encoder & multiplexer -> MPEG2 demux
00410 //
00411 // ----------------------         ---------------------------------------    ---------------
00412 // |                   v|   --->  |                                     |    |             |
00413 // | Capture Filter     |         | Audio / video encoder & Multiplexer |  ->| MPEG2 demux |
00414 // |                   a|   --->  |                                     |    |             |
00415 // ----------------------         ---------------------------------------    ---------------
00416 //
00417 //
00418 //
00419 //
00420 //
00421 //                        -> audio encoder ->
00422 //  2. capture filter                           multiplexer -> MPEG2 demux
00423 //                        -> video encoder ->
00424 //
00425 //  -----------------------     -----------------    ----------------     ---------------
00426 //  |                    a|  -> | audio encoder | -> |              |     |             |
00427 //  |                     |     -----------------    |              |     |             |
00428 //  | capture filter      |                          |  multiplexer |  -> | MPEG2 demux |
00429 //  |                     |     -----------------    |              |     |             |
00430 //  |                    v|  -> | video encoder | -> |              |     |             |
00431 //  -----------------------     -----------------    ----------------     ---------------
00432 //
00433 //
00434 //
00435 //
00436 //
00437 //                      a
00438 //  3.  capture filter      - audio & video encoder -> multiplexer -> MPEG2 demux
00439 //                      v
00440 //
00441 //  -----------------------     -----------------    ----------------     ---------------
00442 //  |                    a|  -> | audio encoder | -> |              |     |             |
00443 //  |                     |     |               |    |              |     |             |
00444 //  | capture filter      |     |               |    |  multiplexer |  -> | MPEG2 demux |
00445 //  |                     |     |               |    |              |     |             |
00446 //  |                    v|  -> | video encoder | -> |              |     |             |
00447 //  -----------------------     -----------------    ----------------     ---------------
00448 //
00449 //
00450 //
00451 //
00452 //  4. capture filter -> MPEG2 demux
00453 //
00454 // ------------------------------       ----------------
00455 // |                   MPEG2 PS | --->  |              |
00456 // | Capture Filter             |       | MPEG2 demux  |
00457 // |                            |       |              |
00458 // ------------------------------       ----------------
00459 //
00460 //
00461 
00462 
00463 //
00464 //  How the algorithm works:
00465 //      1. the video pin doesn't stream MPEG2
00466 //          1. tries to connect the pin to an encoder
00467 //          2. tries to connect the encoder directly to the MPEG2 demux
00468 //          3. if not possible, tries to find a multiplexor that can be connected to the
00469 //             encoder and MPEG2 demux
00470 //          4. connect audio pin to the MPEG2 demux using the same algorithm as in
00471 //             video pin case
00472 //
00473 //      2. if pin streams MPEG2 PS, then connect it to the MPEG2 demux
00474 //      3. program the MPEG2 demux
00475 //      4. render the video and the audio pin from the MPEG2 demux
00476 //
00477 
00478 
00479 static
00480 BYTE
00481 Mpeg2ProgramVideo [] = {
00482     0x00, 0x00, 0x00, 0x00,                         //  .hdr.rcSource.left              = 0x00000000
00483     0x00, 0x00, 0x00, 0x00,                         //  .hdr.rcSource.top               = 0x00000000
00484     0xD0, 0x02, 0x00, 0x00,                         //  .hdr.rcSource.right             = 0x000002d0
00485     0xE0, 0x01, 0x00, 0x00,                         //  .hdr.rcSource.bottom            = 0x000001e0
00486     0x00, 0x00, 0x00, 0x00,                         //  .hdr.rcTarget.left              = 0x00000000
00487     0x00, 0x00, 0x00, 0x00,                         //  .hdr.rcTarget.top               = 0x00000000
00488     0x00, 0x00, 0x00, 0x00,                         //  .hdr.rcTarget.right             = 0x00000000
00489     0x00, 0x00, 0x00, 0x00,                         //  .hdr.rcTarget.bottom            = 0x00000000
00490     0x00, 0x09, 0x3D, 0x00,                         //  .hdr.dwBitRate                  = 0x003d0900
00491     0x00, 0x00, 0x00, 0x00,                         //  .hdr.dwBitErrorRate             = 0x00000000
00492     0x63, 0x17, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, //  .hdr.AvgTimePerFrame            = 0x0000000000051763
00493     0x00, 0x00, 0x00, 0x00,                         //  .hdr.dwInterlaceFlags           = 0x00000000
00494     0x00, 0x00, 0x00, 0x00,                         //  .hdr.dwCopyProtectFlags         = 0x00000000
00495     0x04, 0x00, 0x00, 0x00,                         //  .hdr.dwPictAspectRatioX         = 0x00000004
00496     0x03, 0x00, 0x00, 0x00,                         //  .hdr.dwPictAspectRatioY         = 0x00000003
00497     0x00, 0x00, 0x00, 0x00,                         //  .hdr.dwReserved1                = 0x00000000
00498     0x00, 0x00, 0x00, 0x00,                         //  .hdr.dwReserved2                = 0x00000000
00499     0x28, 0x00, 0x00, 0x00,                         //  .hdr.bmiHeader.biSize           = 0x00000028
00500     0xD0, 0x02, 0x00, 0x00,                         //  .hdr.bmiHeader.biWidth          = 0x000002d0
00501     0xE0, 0x01, 0x00, 0x00,                         //  .hdr.bmiHeader.biHeight         = 0x00000000
00502     0x00, 0x00,                                     //  .hdr.bmiHeader.biPlanes         = 0x0000
00503     0x00, 0x00,                                     //  .hdr.bmiHeader.biBitCount       = 0x0000
00504     0x00, 0x00, 0x00, 0x00,                         //  .hdr.bmiHeader.biCompression    = 0x00000000
00505     0x00, 0x00, 0x00, 0x00,                         //  .hdr.bmiHeader.biSizeImage      = 0x00000000
00506     0xD0, 0x07, 0x00, 0x00,                         //  .hdr.bmiHeader.biXPelsPerMeter  = 0x000007d0
00507     0x27, 0xCF, 0x00, 0x00,                         //  .hdr.bmiHeader.biYPelsPerMeter  = 0x0000cf27
00508     0x00, 0x00, 0x00, 0x00,                         //  .hdr.bmiHeader.biClrUsed        = 0x00000000
00509     0x00, 0x00, 0x00, 0x00,                         //  .hdr.bmiHeader.biClrImportant   = 0x00000000
00510     0x98, 0xF4, 0x06, 0x00,                         //  .dwStartTimeCode                = 0x0006f498
00511     0x56, 0x00, 0x00, 0x00,                         //  .cbSequenceHeader               = 0x00000056
00512     0x02, 0x00, 0x00, 0x00,                         //  .dwProfile                      = 0x00000002
00513     0x02, 0x00, 0x00, 0x00,                         //  .dwLevel                        = 0x00000002
00514     0x00, 0x00, 0x00, 0x00,                         //  .Flags                          = 0x00000000
00515                                                     //  .dwSequenceHeader [1]
00516     0x00, 0x00, 0x01, 0xB3, 0x2D, 0x01, 0xE0, 0x24,
00517     0x09, 0xC4, 0x23, 0x81, 0x10, 0x11, 0x11, 0x12,
00518     0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14,
00519     0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x15,
00520     0x15, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
00521     0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
00522     0x18, 0x18, 0x18, 0x19, 0x18, 0x18, 0x18, 0x19,
00523     0x1A, 0x1A, 0x1A, 0x1A, 0x19, 0x1B, 0x1B, 0x1B,
00524     0x1B, 0x1B, 0x1C, 0x1C, 0x1C, 0x1C, 0x1E, 0x1E,
00525     0x1E, 0x1F, 0x1F, 0x21, 0x00, 0x00, 0x01, 0xB5,
00526     0x14, 0x82, 0x00, 0x01, 0x00, 0x00
00527 } ;
00528 
00529 
00530 static
00531 BYTE
00532 MPEG1AudioFormat [] = {
00533     0x50, 0x00, 0x02, 0x00, 0x80, 0xBB, 0x00, 0x00,
00534     0x00, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
00535     0x16, 0x00, 0x02, 0x00, 0x00, 0xE8, 0x03, 0x00,
00536     0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x1C, 0x00,
00537     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00538 } ;
00539 
00540 
00541 
00542 HRESULT
00543 ISampleCaptureGraphBuilder::AllocCapFile( LPCOLESTR lpwstr, DWORDLONG dwlSize )
00544 {
00545     return graphBuilder2_->AllocCapFile( lpwstr, dwlSize );
00546 }
00547 
00548 
00549 HRESULT
00550 ISampleCaptureGraphBuilder::ControlStream( const GUID *pCategory,
00551                                           const GUID *pType,
00552                                           IBaseFilter *pFilter,
00553                                           REFERENCE_TIME *pstart,
00554                                           REFERENCE_TIME *pstop,
00555                                           WORD wStartCookie,
00556                                           WORD wStopCookie )
00557 {
00558     return graphBuilder2_->ControlStream( pCategory, pType, pFilter,
00559                                           pstart, pstop, wStartCookie, wStopCookie );
00560 }
00561 
00562 
00563 HRESULT
00564 ISampleCaptureGraphBuilder::CopyCaptureFile(  LPOLESTR lpwstrOld,
00565                                               LPOLESTR lpwstrNew,
00566                                               int fAllowEscAbort,
00567                                               IAMCopyCaptureFileProgress *pCallback)
00568 {
00569     return graphBuilder2_->CopyCaptureFile( lpwstrOld, lpwstrNew,
00570                                             fAllowEscAbort, pCallback );
00571 }
00572 
00573 HRESULT ISampleCaptureGraphBuilder::FindInterface(const GUID *pCategory,
00574                                                   const GUID *pType,
00575                                                   IBaseFilter *pf,
00576                                                   REFIID riid,
00577                                                   void **ppint
00578                                                   )
00579 {
00580     return graphBuilder2_->FindInterface( pCategory, pType, pf, riid, ppint );
00581 }
00582 
00583 HRESULT
00584 ISampleCaptureGraphBuilder::FindPin( IUnknown *pSource,
00585                                       PIN_DIRECTION pindir,
00586                                       const GUID *pCategory,
00587                                       const GUID *pType,
00588                                       BOOL fUnconnected,
00589                                       int num,
00590                                       IPin **ppPin)
00591 {
00592     return graphBuilder2_->FindPin( pSource, pindir, pCategory, pType,
00593                                     fUnconnected, num, ppPin );
00594 }
00595 
00596 
00597 HRESULT ISampleCaptureGraphBuilder::GetFiltergraph( IGraphBuilder **ppfg )
00598 {
00599     return graphBuilder2_->GetFiltergraph( ppfg );
00600 }
00601 
00602 HRESULT
00603 ISampleCaptureGraphBuilder::RenderStream( const GUID *pCategory,
00604                                           const GUID *pType,
00605                                           IUnknown *pSource,
00606                                           IBaseFilter *pIntermediate,
00607                                           IBaseFilter *pSink)
00608 {
00609     if( !pType ||  !::IsEqualGUID( MEDIATYPE_Stream, *pType ) )
00610     {
00611         return graphBuilder2_->RenderStream( pCategory, pType, pSource,
00612                                              pIntermediate, pSink );
00613     }
00614 
00615 
00616     HRESULT hr;
00617     if( !graph_ )
00618     {
00619         hr = GetFiltergraph( &graph_ );
00620         if( FAILED( hr ) )
00621         {
00622             return hr;
00623         }
00624     }
00625 
00626     //
00627     //  try to build MPEG2 graph
00628     //
00629     CComPtr< IBaseFilter > captureFilter;
00630 
00631     hr = pSource->QueryInterface( & captureFilter );
00632     if( FAILED( hr ) )
00633     {
00634         return E_INVALIDARG;
00635     }
00636 
00637     hr = BuildMPEG2Segment( captureFilter );
00638     if( pSink || FAILED( hr ) )
00639     {
00640         return hr;
00641     }
00642 
00643     hr = ConfigureMPEG2Demux( pMPEG2Demux_ );
00644     if( FAILED( hr ) )
00645     {
00646         return hr;
00647     }
00648 
00649 // original code:
00650 //    hr = RenderStream(NULL, &MEDIATYPE_Video, pMPEG2Demux_, NULL, NULL );
00651 //    if( FAILED( hr ) )
00652 //    {
00653 //        return hr;
00654 //    }
00655 //
00656 // ________________________________________________
00657 // edited by Alessandro Polo 2006 - eWorld Research
00658 
00659     hr = RenderStream(NULL, &MEDIATYPE_Video, pMPEG2Demux_, NULL, NULL );
00660 //    hr = RenderStream(NULL, NULL, pMPEG2Demux_, NULL, pSink);
00661 
00662     if( FAILED( hr ) )
00663     {
00664         return hr;
00665     }
00666 
00667 
00668 // ________________________________________________
00669 
00670     hr = RenderStream(NULL, &MEDIATYPE_Audio, pMPEG2Demux_, NULL, NULL );
00671     if( FAILED( hr ) )
00672     {
00673         return hr;
00674     }
00675 
00676     return S_OK;
00677 }
00678 
00679 
00680 HRESULT
00681 ISampleCaptureGraphBuilder::SetFiltergraph( IGraphBuilder *pfg )
00682 {
00683     return graphBuilder2_->SetFiltergraph( pfg );
00684 }
00685 
00686 
00687 HRESULT
00688 ISampleCaptureGraphBuilder::SetOutputFileName(  const GUID *pType,
00689                                                 LPCOLESTR lpwstrFile,
00690                                                 IBaseFilter **ppf,
00691                                                 IFileSinkFilter **pSink )
00692 {
00693     if( ! pType || ! lpwstrFile || !ppf || !pSink )
00694     {
00695         return E_INVALIDARG;
00696     }
00697 
00698     if( !::IsEqualGUID( *pType, MEDIASUBTYPE_Mpeg2 ) )
00699     {
00700         return graphBuilder2_->SetOutputFileName(pType, lpwstrFile, ppf, pSink );
00701     }
00702 
00703     HRESULT hr;
00704     if( !graph_ )
00705     {
00706         hr = GetFiltergraph( &graph_ );
00707         if( FAILED( hr ) )
00708         {
00709             return hr;
00710         }
00711     }
00712 
00713     //
00714     //  Configure the dump filter
00715     //
00716     CComPtr< IFileSinkFilter > pDump;
00717     hr = pDump.CoCreateInstance( CLSID_Dump );
00718     if( FAILED( hr ) )
00719     {
00720         return hr;
00721     }
00722 
00723     hr = pDump->SetFileName( lpwstrFile, NULL );
00724     if( FAILED( hr ) )
00725     {
00726         return hr;
00727     }
00728 
00729     hr = pDump.QueryInterface( &pMPEG2Demux_ );
00730     if( FAILED( hr ) )
00731     {
00732         return hr;
00733     }
00734 
00735     hr = graph_->AddFilter( pMPEG2Demux_, L"Dump" );
00736     if( FAILED( hr ) )
00737     {
00738         pMPEG2Demux_ = NULL;
00739         return hr;
00740     }
00741 
00742 
00743     *pSink = pDump;
00744     return S_OK;
00745 }
00746 
00747 
00748 
00749 //
00750 //  A device can stream directly MPEG2 stream,
00751 //  or it can be linked with a video codec and multiplexer
00752 //
00753 //
00754 
00755 //
00756 //  Loop through every media type supported by this pin
00757 //  to see if there is one which can be considered MPEG2
00758 //
00759 BOOL ISampleCaptureGraphBuilder::IsMPEG2Pin( CComPtr<IPin> pPin )
00760 {
00761     if( !pPin )
00762     {
00763         return FALSE;   // NULL pointer
00764     }
00765 
00766     CComPtr<IEnumMediaTypes> pMediaTypes;
00767     HRESULT hr = pPin->EnumMediaTypes( &pMediaTypes );
00768     if( FAILED( hr ) )
00769     {
00770         return FALSE;
00771     }
00772 
00773     hr = pMediaTypes->Reset();
00774     if( FAILED( hr ) )
00775     {
00776         return FALSE;
00777     }
00778 
00779     ULONG           fetched;
00780     AM_MEDIA_TYPE   *mediaType;
00781     while( S_OK == pMediaTypes->Next( 1, &mediaType, &fetched ) )
00782     {
00783         if(
00784             (
00785                 ::IsEqualGUID( mediaType->majortype, MEDIATYPE_Video ) ||
00786                 ::IsEqualGUID( mediaType->majortype, MEDIATYPE_Stream )
00787             )
00788             &&
00789             (
00790                 ::IsEqualGUID( mediaType->subtype, MEDIASUBTYPE_MPEG2_VIDEO ) ||
00791                 ::IsEqualGUID( mediaType->subtype,  MEDIASUBTYPE_MPEG2_PROGRAM )
00792             )
00793         )
00794         {
00795             DeleteMediaType( mediaType );
00796             return TRUE;
00797         }
00798         DeleteMediaType( mediaType );
00799     }
00800 
00801     return FALSE;
00802 }
00803 
00804 BOOL ISampleCaptureGraphBuilder::IsVideoPin( CComPtr<IPin> pPin )
00805 {
00806     return HasMediaType( pPin, MEDIATYPE_Video );
00807 }
00808 
00809 
00810 
00811 HRESULT ISampleCaptureGraphBuilder::GetEncodersByCategory( CComPtr<IEnumMoniker>& pEncoders )
00812 {
00813     CComPtr<ICreateDevEnum> pDeviceEnum;
00814 
00815     HRESULT hr = pDeviceEnum.CoCreateInstance( CLSID_SystemDeviceEnum );
00816     if( FAILED( hr ) )
00817     {
00818         return hr;
00819     }
00820 
00821     return pDeviceEnum->CreateClassEnumerator( KSCATEGORY_ENCODER, &pEncoders, 0 );
00822 }
00823 
00824 
00825 
00826 HRESULT
00827 ISampleCaptureGraphBuilder::GetEncodersByEnumerating(
00828                                         CComPtr< IPin > pPin,
00829                                         const REGPINMEDIUM& pinMedium,
00830                                         CComPtr<IEnumMoniker>& pEncoders )
00831 {
00832     CComPtr<IFilterMapper2> pFilterMapper2;
00833     HRESULT hr = pFilterMapper2.CoCreateInstance( CLSID_FilterMapper2 );
00834     if( FAILED( hr ) )
00835     {
00836         return hr;
00837     }
00838 
00839     hr = pFilterMapper2->EnumMatchingFilters(
00840                                 &pEncoders,
00841                                 NULL,
00842                                 FALSE,
00843                                 0,          //any merit
00844                                 TRUE,
00845                                 0,
00846                                 NULL,
00847                                 &pinMedium,
00848                                 NULL,
00849                                 FALSE,
00850                                 TRUE,
00851                                 0,
00852                                 NULL,
00853                                 NULL,
00854                                 NULL );
00855 
00856 
00857     return hr;
00858 }
00859 
00860 
00861 //
00862 //  looks for an MPEG2 pin
00863 //
00864 HRESULT
00865 ISampleCaptureGraphBuilder::FindMPEG2Pin(
00866                         CComPtr<IBaseFilter> pFilter,
00867                         CComPtr<IPin>& pPin )
00868 {
00869     if( !pFilter )
00870     {
00871         return E_POINTER;
00872     }
00873 
00874 
00875     CComPtr<IEnumPins> pEnumPins;
00876     HRESULT hr = pFilter->EnumPins( &pEnumPins );
00877     if( FAILED( hr ) )
00878     {
00879         return hr;
00880     }
00881 
00882     CComPtr<IPin>   pTempPin;
00883     ULONG           fetched;
00884     PIN_DIRECTION   dir;
00885 
00886     hr = pEnumPins->Reset( );
00887     while( pTempPin.Release(), S_OK == pEnumPins->Next( 1, &pTempPin, &fetched ) )
00888     {
00889         hr = pTempPin->QueryDirection( &dir );
00890         if( FAILED( hr ) || PINDIR_INPUT == dir )
00891         {
00892             continue;
00893         }
00894         if( IsMPEG2Pin( pTempPin ) )
00895         {
00896             pPin = pTempPin;
00897             return S_OK;
00898         }
00899     }
00900     return E_FAIL;
00901 }
00902 
00903 //
00904 //  search the encoder that has this special medium
00905 //  video == TRUE -- look for a video pin
00906 //  video == FALSE -- look for a audio pin
00907 //
00908 HRESULT ISampleCaptureGraphBuilder::FindPin(
00909             CComPtr<IBaseFilter> pFilter,
00910             const REGPINMEDIUM& regPinMedium,
00911             PIN_DIRECTION direction,
00912             BOOL video,
00913             CComPtr<IPin>& pPin)
00914 {
00915     if( !pFilter )
00916     {
00917         return E_POINTER;
00918     }
00919 
00920     CComPtr<IEnumPins> pEnumPins;
00921     HRESULT hr = pFilter->EnumPins( &pEnumPins );
00922     if( FAILED( hr ) )
00923     {
00924         return hr;
00925     }
00926 
00927     CComPtr<IPin>   pTempPin;
00928     ULONG           fetched;
00929     REGPINMEDIUM    regPinMediumTemp;
00930     PIN_DIRECTION   dir;
00931 
00932     hr = pEnumPins->Reset( );
00933     while( pTempPin.Release(), S_OK == pEnumPins->Next( 1, &pTempPin, &fetched ) )
00934     {
00935         ASSERT( pTempPin );
00936 
00937         hr = pTempPin->QueryDirection( &dir );
00938         if( FAILED( hr ) || dir != direction )
00939         {
00940             continue;
00941         }
00942 
00943         hr = GetMedium( pTempPin, regPinMediumTemp );
00944         if( FAILED( hr ) )
00945         {
00946             continue;
00947         }
00948 
00949         if( !IsVideoPin( pTempPin ) )
00950         {
00951             continue;
00952         }
00953 
00954         if( ::IsEqualGUID( regPinMediumTemp.clsMedium, regPinMedium.clsMedium  ) &&
00955             regPinMediumTemp.dw1 == regPinMedium.dw1 )
00956         {
00957             pPin = pTempPin;
00958             return S_OK;
00959         }
00960     }
00961 
00962     return E_FAIL;
00963 }
00964 
00965 //
00966 //  Get a special medium from this pin.
00967 //  If there is not one, return GUID_NULL.
00968 //  Returns the first one it finds special
00969 //
00970 
00971 HRESULT
00972 ISampleCaptureGraphBuilder::GetMedium(
00973                         CComPtr<IPin> pPin,
00974                         REGPINMEDIUM& regPinMedium )
00975 {
00976     if( !pPin )
00977     {
00978         return E_POINTER;
00979     }
00980 
00981     CComPtr<IKsPin> pKsPin;
00982     HRESULT hr = pPin.QueryInterface( &pKsPin );
00983     if( FAILED( hr ) )
00984     {
00985         return hr;
00986     }
00987 
00988     PKSMULTIPLE_ITEM pmi;
00989     hr = pKsPin->KsQueryMediums( &pmi );
00990     if( FAILED( hr ) )
00991     {
00992         return hr;
00993     }
00994 
00995     REGPINMEDIUM *pMedium = (REGPINMEDIUM *)(pmi + 1);
00996     for( ULONG i  = 0; i < pmi->Count; i++ )
00997     {
00998         if( !::IsEqualGUID( pMedium->clsMedium, GUID_NULL ) &&
00999             !::IsEqualGUID( pMedium->clsMedium, KSMEDIUMSETID_Standard )
01000         )
01001         {
01002             regPinMedium.clsMedium = pMedium->clsMedium;
01003             regPinMedium.dw1 = pMedium->dw1;
01004             regPinMedium.dw2 = pMedium->dw2;
01005             CoTaskMemFree( pmi );
01006             return S_OK;
01007         }
01008     }
01009 
01010     regPinMedium.clsMedium = GUID_NULL;
01011     regPinMedium.dw1 = 0;
01012     regPinMedium.dw2 = 0;
01013     CoTaskMemFree( pmi );
01014     return S_OK;
01015 }
01016 
01017 
01018 
01019 //
01020 //  Adds the MPEG2 demux and renders
01021 //  the audio and video pin until the end (until the renderers)
01022 //
01023 
01024 HRESULT ISampleCaptureGraphBuilder::AddMPEG2Demux( )
01025 {
01026     if( pMPEG2Demux_ )
01027     {
01028         //
01029         //  Instead of a MPEG2 demux there is a
01030         //  dump filter in which the file will be dumped
01031         //
01032         return S_OK;
01033     }
01034 
01035     HRESULT hr = pMPEG2Demux_.CoCreateInstance(CLSID_MPEG2Demultiplexer);
01036     if( FAILED( hr ) )
01037     {
01038         return hr;
01039     }
01040     return graph_->AddFilter( static_cast<IBaseFilter *>( pMPEG2Demux_ ), L"MPEG2 Demux" );
01041 }
01042 
01043 
01044 
01045 HRESULT
01046 ISampleCaptureGraphBuilder::FindVideoPin(
01047                                 CComPtr<IBaseFilter> pFilter,
01048                                 CComPtr<IPin>& pPin  )
01049 {
01050     if( !pFilter )
01051     {
01052         return E_POINTER;
01053     }
01054 
01055     CComPtr<IEnumPins> pEnumPins;
01056     HRESULT hr = pFilter->EnumPins( &pEnumPins );
01057     if( FAILED( hr ) )
01058     {
01059         return hr;
01060     }
01061 
01062     CComPtr<IPin>   pTempPin;
01063     ULONG           fetched;
01064     hr = pEnumPins->Reset( );
01065 
01066     while( pTempPin.Release(), S_OK == pEnumPins->Next( 1, &pTempPin, &fetched ) )
01067     {
01068         if( IsVideoPin( pTempPin ) )
01069         {
01070 #ifdef DEBUG
01071             USES_CONVERSION;
01072             PIN_INFO info;
01073             pTempPin->QueryPinInfo( &info );
01074             info.pFilter->Release( );
01075 #endif
01076             pPin = pTempPin;
01077             return S_OK;
01078         }
01079     }
01080     return E_FAIL;
01081 }
01082 
01083 BOOL ISampleCaptureGraphBuilder::IsAudioPin( CComPtr<IPin> pPin )
01084 {
01085     if( !pPin )
01086     {
01087         return FALSE;   // NULL pointer
01088     }
01089 
01090     return HasMediaType( pPin, MEDIATYPE_Audio) ;
01091 }
01092 
01093 
01094 BOOL ISampleCaptureGraphBuilder::HasMediaType(CComPtr<IPin> pPin,  REFGUID majorType )
01095 {
01096     if( !pPin )
01097     {
01098         return FALSE;
01099     }
01100 
01101     CComPtr<IEnumMediaTypes> pMediaTypes;
01102     HRESULT hr = pPin->EnumMediaTypes( &pMediaTypes );
01103     if( FAILED( hr ) )
01104     {
01105         return FALSE;
01106     }
01107 
01108     hr = pMediaTypes->Reset();
01109     if( FAILED( hr ) )
01110     {
01111         return FALSE;
01112     }
01113 
01114     ULONG           fetched;
01115     AM_MEDIA_TYPE   *mediaType;
01116 
01117     while( S_OK == pMediaTypes->Next( 1, &mediaType, &fetched ) )
01118     {
01119         if( ::IsEqualGUID( mediaType->majortype, majorType ) )
01120         {
01121             DeleteMediaType( mediaType );
01122             return TRUE;
01123         }
01124         DeleteMediaType( mediaType );
01125     }
01126 
01127     return FALSE;
01128 
01129 }
01130 
01131 
01132 HRESULT
01133 ISampleCaptureGraphBuilder::FindAudioPin(
01134                                 CComPtr<IBaseFilter> pFilter,
01135                                 CComPtr<IPin>& pPin  )
01136 {
01137     if( !pFilter )
01138     {
01139         return E_POINTER;
01140     }
01141 
01142     CComPtr<IEnumPins> pEnumPins;
01143     HRESULT hr = pFilter->EnumPins( &pEnumPins );
01144     if( FAILED( hr ) )
01145     {
01146         return hr;
01147     }
01148 
01149     CComPtr<IPin>   pTempPin;
01150     ULONG           fetched;
01151     hr = pEnumPins->Reset( );
01152 
01153     while( pTempPin.Release(), S_OK == pEnumPins->Next( 1, &pTempPin, &fetched ) )
01154     {
01155         if( IsAudioPin( pTempPin ) )
01156         {
01157 #ifdef DEBUG
01158             USES_CONVERSION;
01159             PIN_INFO info;
01160             pTempPin->QueryPinInfo( &info );
01161             info.pFilter->Release( );
01162 #endif
01163             pPin = pTempPin;
01164             return S_OK;
01165         }
01166     }
01167     return E_FAIL;
01168 }
01169 
01170 
01171 
01172 HRESULT ISampleCaptureGraphBuilder::FindEncoder(
01173                 CComPtr<IEnumMoniker> pEncoders,
01174                 REGPINMEDIUM pinMedium,
01175                 CComPtr<IBaseFilter>& pEncoder  )
01176 {
01177     if( ! pEncoders )
01178     {
01179         return E_INVALIDARG;
01180     }
01181 
01182     if( IsEqualGUID( pinMedium.clsMedium, GUID_NULL ) ||
01183         IsEqualGUID( pinMedium.clsMedium, KSMEDIUMSETID_Standard ) )
01184     {
01185         return E_INVALIDARG;
01186     }
01187 
01188     HRESULT                 hr;
01189     CComPtr<IBaseFilter>    pFilter;
01190     CComPtr<IMoniker>       pMoniker;
01191     ULONG                   fetched;
01192     CComPtr<IPin>           pPin;
01193 
01194     while( pFilter.Release(), pMoniker.Release(),
01195            S_OK == pEncoders->Next( 1, &pMoniker, &fetched ) )
01196     {
01197         hr = pMoniker->BindToObject(
01198             0, 0, IID_IBaseFilter, reinterpret_cast<void **>( &pFilter ) );
01199         if( FAILED( hr ) )
01200         {
01201             continue;
01202         }
01203 
01204         hr = FindPin( pFilter, pinMedium, PINDIR_INPUT, TRUE, pPin );
01205         if( SUCCEEDED( hr ) )
01206         {
01207             pEncoder = pFilter;
01208             return hr;
01209         }
01210     }
01211 
01212     return E_FAIL;
01213 }
01214 
01215 
01216 
01217 HRESULT
01218 ISampleCaptureGraphBuilder::RenderToMPEG2Demux(
01219                             CComPtr<IPin> pPin,
01220                             CComPtr<IEnumMoniker> pEncoders)
01221 {
01222     if( !pPin || !pEncoders )
01223     {
01224         return E_INVALIDARG;
01225     }
01226 
01227     REGPINMEDIUM pinMedium ;
01228     pinMedium.clsMedium = GUID_NULL;
01229     pinMedium.dw1 = 0;
01230     pinMedium.dw2 = 0;
01231 
01232     CComPtr<IBaseFilter> pFilter;
01233     CComPtr<IMoniker>    pMoniker;
01234     ULONG                fetched;
01235     HRESULT              hr;
01236 
01237     while( pFilter.Release(), pMoniker.Release(), S_OK == pEncoders->Next( 1, &pMoniker, &fetched ) )
01238     {
01239         hr = pMoniker->BindToObject(
01240             0, 0, IID_IBaseFilter, reinterpret_cast<void **>( &pFilter ) );
01241         if( FAILED( hr ) )
01242         {
01243             continue;
01244         }
01245 
01246         hr = graph_->AddFilter( pFilter, L"Encoder" );
01247         if( FAILED( hr ) )
01248         {
01249             continue;
01250         }
01251 
01252         hr = ConnectPin( pPin, pFilter );
01253         if( FAILED( hr ) )
01254         {
01255             graph_->RemoveFilter( pFilter );
01256             continue;
01257         }
01258 
01259         hr = ConnectEncoderToMPEG2Demux( pFilter, pinMedium );
01260         if( SUCCEEDED( hr ) )
01261         {
01262             pEncoder_ = pFilter;
01263             return S_OK;
01264         }
01265         graph_->RemoveFilter( pFilter );
01266     }
01267 
01268     return E_FAIL;
01269 }
01270 
01271 
01272 //
01273 //  Loop through every encoder available on system.
01274 //  Look first after the one that has a special medium if
01275 //  there is a special one on pPin.
01276 //  Otherwise, try to render using ICaptureGrapBuilder2
01277 //  and the encoder that matches this will be the chosen one/
01278 //  If the encoder is found, then this will be rendered to the
01279 //  MPEG2 demux.
01280 //
01281 
01282 HRESULT
01283     ISampleCaptureGraphBuilder::RenderToMPEG2Demux(
01284         CComPtr<IPin> pPin,
01285         const REGPINMEDIUM& pinMedium,
01286         CComPtr<IEnumMoniker> pEncoders
01287 )
01288 {
01289     //
01290     //  The pin has a special medium,
01291     //  there shold be an encoder with the same
01292     //  medium
01293     //
01294     CComPtr< IBaseFilter > pEncoder;
01295     HRESULT hr = FindEncoder( pEncoders, pinMedium, pEncoder );
01296     if( FAILED( hr ) )
01297     {
01298         return hr;
01299     }
01300 
01301     hr = graph_->AddFilter( pEncoder, L"Encoder" );
01302     if( FAILED( hr ) )
01303     {
01304         return hr;
01305     }
01306 
01307     hr = ConnectPin( pPin, pEncoder );
01308     if( FAILED(  hr ) )
01309     {
01310         hr = graph_->RemoveFilter( pEncoder );
01311         return hr;
01312     }
01313 
01314     //
01315     //  the video pin was rendered to the same
01316     //  ( hardware? ) encoder with the same mediu
01317     //
01318     hr = ConnectEncoderToMPEG2Demux( pEncoder, pinMedium );
01319     if( FAILED( hr ) )
01320     {
01321         hr = graph_->RemoveFilter( pEncoder );
01322         return hr;
01323     }
01324 
01325     pEncoder_ = pEncoder;
01326     return S_OK;
01327 }
01328 
01329 
01330 
01331 HRESULT
01332 ISampleCaptureGraphBuilder::RenderToMPEG2Demux( CComPtr<IPin> pPin )
01333 {
01334     if( !pPin )
01335     {
01336         return E_INVALIDARG;
01337     }
01338 
01339     REGPINMEDIUM pinMedium;
01340     HRESULT hr = GetMedium( pPin, pinMedium );
01341     if( FAILED( hr ) )
01342     {
01343         return hr;
01344     }
01345 
01346 
01347     CComPtr< IEnumMoniker > pEncoders;
01348     if( ::IsEqualGUID( pinMedium.clsMedium, GUID_NULL ) )
01349     {
01350         //
01351         //  Search throgh the codec category
01352         //
01353         hr = GetEncodersByCategory( pEncoders );
01354         if( FAILED( hr ) )
01355         {
01356                 return hr;
01357         }
01358 
01359         hr = RenderToMPEG2Demux( pPin, pEncoders );
01360         if( SUCCEEDED( hr ) )
01361         {
01362             return S_OK;
01363         }
01364     }
01365     else
01366     {
01367         //
01368         //  search through encoders category; identify
01369         //  the encoder using the medium
01370         //
01371         hr = GetEncodersByCategory( pEncoders );
01372         if( FAILED( hr ) )
01373         {
01374             return hr;
01375         }
01376 
01377         hr = RenderToMPEG2Demux( pPin, pinMedium, pEncoders  );
01378         if( SUCCEEDED( hr ) )
01379         {
01380             return S_OK;
01381         }
01382 
01383         pEncoders = NULL;
01384         hr = GetEncodersByEnumerating( pPin, pinMedium, pEncoders );
01385         if( FAILED( hr ) )
01386         {
01387             return hr;
01388         }
01389 
01390         hr = RenderToMPEG2Demux( pPin, pinMedium, pEncoders );
01391         if( FAILED( hr ) )
01392         {
01393             return hr;
01394         }
01395     }
01396     return S_OK;
01397 }
01398 
01399 
01400 //
01401 //  pEncoder - the encoder to be connected using a multiplexer
01402 //
01403 //
01404 HRESULT
01405 ISampleCaptureGraphBuilder::ConnectEncoderToMPEG2Demux(
01406                 CComPtr< IBaseFilter > pEncoder,
01407                 const REGPINMEDIUM& pinMedium )
01408 {
01409 
01410     REGPINMEDIUM regPinMedium ;
01411     regPinMedium.clsMedium = GUID_NULL;
01412     regPinMedium.dw1 = 0;
01413     regPinMedium.dw2 = 0;
01414     //
01415     //  try a direct connection between
01416     //  codec and MPEG2Demux
01417     //
01418     HRESULT hr = ConnectFilters(
01419                         pEncoder,
01420                         pMPEG2Demux_ );
01421     if( SUCCEEDED( hr ) )
01422     {
01423         return S_OK;
01424     }
01425 
01426     //
01427     //  no luck
01428     //  maybe I need a multiplexer
01429     //
01430     CComPtr< IEnumMoniker > pMultiplexers;
01431     hr = GetMultiplexersByCategory( pMultiplexers );
01432     if( FAILED( hr ) )
01433     {
01434         return hr;
01435     }
01436     hr = ConnectMultiplexerToMPEG2Demux( pEncoder, pMultiplexers );
01437     if( SUCCEEDED( hr ) )
01438     {
01439         return S_OK;
01440     }
01441 
01442     if( FALSE == ::IsEqualGUID( pinMedium.clsMedium, GUID_NULL ) )
01443     {
01444         //
01445         //  get the multiplexers using IFilterMapper2
01446         //  assuming that the encoder and the multiplexer have the same medium
01447         //
01448         pMultiplexers = NULL;
01449         hr = GetMultiplexersByFilterMapper( pMultiplexers, pinMedium );
01450         if( FAILED( hr ) )
01451         {
01452             return hr;
01453         }
01454         hr = ConnectMultiplexerToMPEG2Demux( pEncoder, pMultiplexers );
01455         if( SUCCEEDED( hr ) )
01456         {
01457             return S_OK;
01458         }
01459     }
01460     return E_FAIL;
01461 }
01462 
01463 
01464 HRESULT
01465 ISampleCaptureGraphBuilder::GetMultiplexersByCategory( CComPtr<IEnumMoniker>& pMultiplexers )
01466 {
01467     CComPtr<ICreateDevEnum> pDeviceEnum;
01468 
01469     HRESULT hr = pDeviceEnum.CoCreateInstance( CLSID_SystemDeviceEnum );
01470     if( FAILED( hr ) )
01471     {
01472         return hr;
01473     }
01474 
01475     return pDeviceEnum->CreateClassEnumerator( KSCATEGORY_MULTIPLEXER, &pMultiplexers, 0 );
01476 }
01477 
01478 HRESULT
01479 ISampleCaptureGraphBuilder::GetMultiplexersByFilterMapper(
01480                                     CComPtr<IEnumMoniker>& pMultiplexers,
01481                                     const REGPINMEDIUM& pinMedium  )
01482 {
01483     return E_NOTIMPL;
01484 }
01485 
01486 
01487 HRESULT
01488 ISampleCaptureGraphBuilder::ConnectMultiplexerToMPEG2Demux(
01489                                         CComPtr<IBaseFilter> pEncoder,
01490                                         CComPtr< IEnumMoniker > pMultiplexers )
01491 {
01492     if( !pEncoder || !pMultiplexers )
01493     {
01494         return E_INVALIDARG;
01495     }
01496 
01497     CComPtr<IBaseFilter> pFilter;
01498     CComPtr<IMoniker>   pMoniker;
01499     ULONG               fetched;
01500     HRESULT             hr;
01501 
01502     while( pFilter.Release(), pMoniker.Release(),
01503            S_OK == pMultiplexers->Next( 1, &pMoniker, &fetched ) )
01504     {
01505         hr = pMoniker->BindToObject(
01506             0, 0, IID_IBaseFilter, reinterpret_cast<void **>( &pFilter ) );
01507         if( FAILED( hr ) )
01508         {
01509             continue;
01510         }
01511 
01512         hr = graph_->AddFilter( pFilter, NULL );
01513         if( FAILED( hr ) )
01514         {
01515             continue;
01516         }
01517 
01518         //
01519         //  connect the encoder to the multiplexer
01520         //
01521         hr = ConnectFilters( pEncoder, pFilter );
01522         if( FAILED( hr ) )
01523         {
01524             graph_->RemoveFilter( pFilter );
01525             continue;
01526         }
01527 
01528         //
01529         //  connect the multiplexer to the encoder
01530         //
01531         hr = ConnectFilters( pFilter, pMPEG2Demux_ );
01532         if( SUCCEEDED( hr ) )
01533         {
01534             pMultiplexer_ = pFilter;
01535             return S_OK;
01536         }
01537 
01538     }
01539 
01540     return E_FAIL;
01541 }
01542 
01543 
01544 HRESULT
01545 ISampleCaptureGraphBuilder::BuildMPEG2Segment(CComPtr<IBaseFilter> pFilter)
01546 {
01547 
01548     if( ! pFilter )
01549     {
01550         return E_FAIL;
01551     }
01552 
01553 
01554     HRESULT hr = AddMPEG2Demux( );
01555     if( FAILED( hr ) )
01556     {
01557         return hr;
01558     }
01559 
01560     //
01561     //  Search a MPEG2 pin on the
01562     //  filter
01563     //
01564     CComPtr<IPin> pPin;
01565     hr = FindMPEG2Pin( pFilter, pPin );
01566     if( SUCCEEDED( hr ) )
01567     {
01568         hr = ConnectPin( pPin, pMPEG2Demux_ );
01569         if( FAILED( hr ) )
01570         {
01571             graph_->RemoveFilter( pMPEG2Demux_ );
01572             return E_FAIL;
01573         }
01574         return S_OK;
01575     }
01576 
01577     //
01578     //  no pins that streams directly MPEG2 stream
01579     //
01580     hr = FindVideoPin( pFilter, pPin );
01581     if( FAILED( hr ) )
01582     {
01583         graph_->RemoveFilter( pMPEG2Demux_ );
01584         return hr; // no video pin
01585     }
01586 
01587     hr = RenderToMPEG2Demux( pPin );
01588     if( FAILED( hr ) )
01589     {
01590         graph_->RemoveFilter( pMPEG2Demux_ );
01591         return hr;
01592     }
01593 
01594     CComPtr<IPin> pAudioPin;
01595     hr = FindAudioPin( pFilter, pAudioPin );
01596     if( FAILED( hr ) )
01597     {
01598         //
01599         //  don't bother with audio
01600         //
01601         return S_OK;
01602     }
01603 
01604     //
01605     //  try to connect the audio pin directly to encoder
01606     //  if this is not possible, then try to find an encoder
01607     //  and connect it to the multiplexer
01608     //
01609     ASSERT( pEncoder_ );
01610     hr = ConnectPin( pAudioPin, pEncoder_ );
01611     if( FAILED( hr ) )
01612     {
01613         hr = ConnectAudioPinToMultiplexer( pAudioPin, pMultiplexer_ );
01614     }
01615 
01616     return S_OK;
01617 }
01618 
01619 
01620 HRESULT
01621 ISampleCaptureGraphBuilder::ConnectAudioPinToMultiplexer(
01622                                             CComPtr<IPin> pPin,
01623                                             CComPtr<IBaseFilter> pMultiplexer)
01624 {
01625     if( !pPin || !pMultiplexer )
01626     {
01627         return E_INVALIDARG;
01628     }
01629 
01630     REGPINMEDIUM pinMedium;
01631     HRESULT hr = GetMedium( pPin, pinMedium );
01632     if( FAILED( hr ) )
01633     {
01634         return hr;
01635     }
01636 
01637     CComPtr<IBaseFilter> pEncoder;
01638     CComPtr<IEnumMoniker> pEncoders;
01639 
01640     if( FALSE == ::IsEqualGUID( pinMedium.clsMedium, GUID_NULL ) )
01641     {
01642         //
01643         //  search through encoders category; identify
01644         //  the encoder using the medium
01645         //
01646         hr = GetEncodersByCategory( pEncoders );
01647         if( FAILED( hr ) )
01648         {
01649             return hr;
01650         }
01651 
01652         hr = FindEncoder( pEncoders, pinMedium, pEncoder );
01653         if( SUCCEEDED( hr ) )
01654         {
01655             hr = graph_->AddFilter( pEncoder, L"Audio Encoder" );
01656             if( SUCCEEDED( hr ) &&
01657                 SUCCEEDED( ConnectPin( pPin, pEncoder ) ) &&
01658                 SUCCEEDED( ConnectFilters( pEncoder, pMultiplexer ) )
01659             )
01660             {
01661                 return S_OK;
01662             }
01663         }
01664 
01665 
01666         pEncoders = NULL;
01667         hr = GetEncodersByEnumerating( pPin, pinMedium, pEncoders );
01668         if( FAILED( hr ) )
01669         {
01670             return hr;
01671         }
01672 
01673         hr = FindEncoder( pEncoders, pinMedium, pEncoder );
01674         if( SUCCEEDED( hr ) )
01675         {
01676             hr = graph_->AddFilter( pEncoder, L"Audio Encoder" );
01677             if( SUCCEEDED( hr ) &&
01678                 SUCCEEDED( ConnectPin( pPin, pEncoder ) ) &&
01679                 SUCCEEDED( ConnectFilters( pEncoder, pMultiplexer ) )
01680             )
01681             {
01682                 return S_OK;
01683             }
01684         }
01685         return E_FAIL;
01686     }
01687 
01688 
01689     //
01690     //  Search throgh the codec category
01691     //
01692     hr = GetEncodersByCategory( pEncoders );
01693     if( FAILED( hr ) )
01694     {
01695         return hr;
01696     }
01697 
01698 
01699     CComPtr<IBaseFilter>    pFilter;
01700     CComPtr<IMoniker>       pMoniker;
01701     ULONG                   fetched;
01702     while( pFilter.Release(), pMoniker.Release(), S_OK == pEncoders->Next( 1, &pMoniker, &fetched ) )
01703     {
01704         hr = pMoniker->BindToObject(
01705             0, 0, IID_IBaseFilter, reinterpret_cast<void **>( &pFilter ) );
01706         if( FAILED( hr ) )
01707         {
01708             continue;
01709         }
01710 
01711         hr = graph_->AddFilter( pFilter, L"Audio Encoder" );
01712         if( FAILED( hr ) )
01713         {
01714             continue;
01715         }
01716 
01717         hr = ConnectPin( pPin, pFilter );
01718         if( FAILED( hr ) )
01719         {
01720             graph_->RemoveFilter( pFilter );
01721             continue;
01722         }
01723 
01724         hr = ConnectFilters( pFilter, pMultiplexer );
01725         if( SUCCEEDED( hr ) )
01726         {
01727             return S_OK;
01728         }
01729         graph_->RemoveFilter( pFilter );
01730     }
01731 
01732     return E_FAIL;
01733 
01734 }
01735 
01736 
01737 HRESULT
01738 ISampleCaptureGraphBuilder::CreateVideoPin(
01739         CComPtr<IMpeg2Demultiplexer> pIMpeg2Demux )
01740 {
01741     if( !pIMpeg2Demux )
01742     {
01743         return E_INVALIDARG;
01744     }
01745 
01746     AM_MEDIA_TYPE amTypeVideo;
01747     amTypeVideo.majortype = MEDIATYPE_Video;
01748     amTypeVideo.subtype = MEDIASUBTYPE_MPEG2_VIDEO;
01749     amTypeVideo.bFixedSizeSamples = TRUE;
01750     amTypeVideo.bTemporalCompression = 0;
01751     amTypeVideo.formattype = FORMAT_MPEG2Video;
01752     amTypeVideo.pUnk = NULL;
01753     amTypeVideo.cbFormat = sizeof( Mpeg2ProgramVideo );
01754     amTypeVideo.pbFormat = Mpeg2ProgramVideo;
01755 
01756     //
01757     // Create video pin
01758     //
01759 
01760     CComPtr<IPin> pVideoOutPin;
01761     HRESULT hr = pIMpeg2Demux->CreateOutputPin( &amTypeVideo, L"MpegVideo", &pVideoOutPin );
01762     if( FAILED( hr ) )
01763     {
01764         return hr;
01765     }
01766 
01767 
01768     CComPtr<IMPEG2StreamIdMap> pIVideoPIDMap;
01769     hr = pVideoOutPin->QueryInterface( &pIVideoPIDMap );
01770     if( FAILED( hr ) )
01771     {
01772         return hr;
01773     }
01774 
01775     hr = pIVideoPIDMap->MapStreamId(VidPID_, MPEG2_PROGRAM_ELEMENTARY_STREAM , 0, 0);
01776     if( FAILED( hr ) )
01777     {
01778         return hr;
01779     }
01780 
01781 
01782 #ifdef USE_VMR
01783     //
01784     //  Get the VMR interface and add it to the graph
01785     //
01786     CComPtr<IBaseFilter> pVMR;
01787     hr = pVMR.CoCreateInstance( CLSID_VideoMixingRenderer );
01788     if( FAILED( hr ) )
01789     {
01790         return hr;
01791     }
01792 
01793     hr = graph_->AddFilter( pVMR, L"VMR" );
01794     if( FAILED( hr ) )
01795     {
01796         return hr;
01797     }
01798 
01799     //
01800     //before rendering the VMR, make the number of streams 1
01801     //
01802     CComPtr<IVMRFilterConfig> pConfig;
01803     hr = pVMR.QueryInterface( &pConfig );
01804     if( FAILED( hr ) )
01805     {
01806         return hr;
01807     }
01808     hr = pConfig->SetNumberOfStreams( 1 );
01809     if( FAILED( hr ) )
01810     {
01811         return hr;
01812     }
01813 
01814 
01815     //
01816     //  Get the input pin from the VMR
01817     //
01818     CComPtr<IPin> pInputPin;
01819     hr = graphBuilder2_->FindPin(
01820             static_cast<IBaseFilter *>( pVMR ),
01821             PINDIR_INPUT,
01822             NULL,
01823             NULL,
01824             TRUE,
01825             0,
01826             &pInputPin
01827         );
01828     if( FAILED( hr ) )
01829     {
01830 
01831         hr = pIMpeg2Demux->DeleteOutputPin(L"MpegVideo");
01832         graph_->RemoveFilter( pVMR );
01833         return hr;
01834     }
01835 
01836     return graph_->Connect( pVideoOutPin, pInputPin );
01837 #endif
01838 
01839     return hr;
01840 }
01841 
01842 
01843 
01844 HRESULT
01845 ISampleCaptureGraphBuilder::CreateAudioPin(
01846             CComPtr<IMpeg2Demultiplexer> pIMpeg2Demux
01847     )
01848 {
01849     if( !pIMpeg2Demux )
01850     {
01851         return E_INVALIDARG;
01852     }
01853 
01854     //
01855     // for audio: could be Mpeg1, Mpeg2, AC3: if Mpeg1 failed (connect failed) try Mpeg2.if failed tried AC3
01856     // Audio struct of AC3 can be copied from dev code.
01857     //
01858     AM_MEDIA_TYPE amTypeAudio;
01859     amTypeAudio.majortype   = MEDIATYPE_Audio;
01860     amTypeAudio.subtype     = MEDIASUBTYPE_MPEG2_AUDIO;
01861     amTypeAudio.bFixedSizeSamples = TRUE;
01862     amTypeAudio.bTemporalCompression = 0;
01863     amTypeAudio.formattype  = FORMAT_WaveFormatEx;
01864     amTypeAudio.pUnk        = NULL;
01865     amTypeAudio.cbFormat    = sizeof( MPEG1AudioFormat );
01866     amTypeAudio.pbFormat    = MPEG1AudioFormat;
01867 
01868 
01869     CComPtr<IPin> pAudioOutPin;
01870     HRESULT hr = pIMpeg2Demux->CreateOutputPin(&amTypeAudio, L"MpegAudio", &pAudioOutPin);
01871     if( FAILED( hr ) )
01872     {
01873         return hr;
01874     }
01875 
01876     CComPtr<IMPEG2StreamIdMap> pIAudioPIDMap;
01877     hr = pAudioOutPin->QueryInterface( &pIAudioPIDMap );
01878     if( FAILED( hr ) )
01879     {
01880         return hr;
01881     }
01882 
01883     hr = pIAudioPIDMap->MapStreamId(AudPID_, MPEG2_PROGRAM_ELEMENTARY_STREAM, 0, 0);
01884     if( FAILED( hr ) )
01885     {
01886         return hr;
01887     }
01888 
01889     /*
01890     //
01891     //  Get the audio renderer
01892     //
01893     CComPtr<IBaseFilter> pAudioRenderer;
01894     hr = pAudioRenderer.CoCreateInstance( CLSID_AudioRender );
01895     if( FAILED( hr ) )
01896     {
01897         return hr;
01898     }
01899 
01900     hr = graph_->AddFilter( pAudioRenderer, L"Audio renderer" );
01901     if( FAILED( hr ) )
01902     {
01903         return hr;
01904     }
01905 
01906     CComPtr<IPin> pInputPin;
01907     hr = graphBuilder2_->FindPin(
01908             static_cast<IBaseFilter *>( pAudioRenderer ),
01909             PINDIR_INPUT,
01910             NULL,
01911             NULL,
01912             TRUE,
01913             0,
01914             &pInputPin
01915         );
01916 
01917     hr = graph_->Connect( pAudioOutPin, pInputPin );
01918     if(FAILED( hr ))
01919     {
01920         hr = pIMpeg2Demux->DeleteOutputPin(L"MpegAudio");
01921         graph_->RemoveFilter( pAudioRenderer );
01922     }
01923 */
01924 
01925     return hr;
01926 }
01927 
01928 
01929 
01930 HRESULT ISampleCaptureGraphBuilder::ConfigureMPEG2Demux( CComPtr<IBaseFilter> pFilter)
01931 {
01932 
01933     if( ! pFilter )
01934     {
01935         return E_INVALIDARG;
01936     }
01937 
01938     //
01939     // Create video pin and render it
01940     //
01941     CComPtr<IMpeg2Demultiplexer> pIMpeg2Demux;
01942     HRESULT hr = pFilter.QueryInterface( &pIMpeg2Demux );
01943     if( FAILED( hr ) )
01944     {
01945         return hr;
01946     }
01947 
01948     hr = CreateVideoPin( pIMpeg2Demux );
01949     if( FAILED( hr ) )
01950     {
01951         return hr;
01952     }
01953 
01954     hr = CreateAudioPin( pIMpeg2Demux );
01955     if( FAILED( hr ) )
01956     {
01957         return hr;
01958     }
01959 
01960     return S_OK;
01961 }
01962 
01963 
01964 HRESULT
01965 ISampleCaptureGraphBuilder::ConnectFilters(CComPtr<IBaseFilter> pUpFilter, CComPtr<IBaseFilter> pDownFilter)
01966 {
01967     if( !pUpFilter || !pDownFilter )
01968     {
01969         return E_INVALIDARG;
01970     }
01971 
01972     // All the need pin & pin enumerator pointers
01973     CComPtr<IEnumPins>  pEnumUpFilterPins ,
01974                         pEnumDownFilterPins;
01975 
01976     CComPtr<IPin>   pUpFilterPin ,
01977                     pDownFilterPin;
01978 
01979     HRESULT hr = S_OK;
01980 
01981     // Get the pin enumerators for both the filtera
01982     hr = pUpFilter->EnumPins(&pEnumUpFilterPins);
01983     if( FAILED( hr ) )
01984     {
01985         return hr;
01986     }
01987 
01988     hr= pDownFilter->EnumPins(&pEnumDownFilterPins);
01989     if( FAILED( hr ) )
01990     {
01991         return hr;
01992     }
01993 
01994 
01995     // Loop on every pin on the Upstream Filter
01996     BOOL bConnected = FALSE;
01997     PIN_DIRECTION pinDir;
01998     ULONG nFetched = 0;
01999     while(pUpFilterPin.Release( ), S_OK == pEnumUpFilterPins->Next(1, &pUpFilterPin, &nFetched) )
02000     {
02001         // Make sure that we have the output pin of the upstream filter
02002         hr = pUpFilterPin->QueryDirection( &pinDir );
02003         if( FAILED( hr ) || PINDIR_INPUT == pinDir )
02004         {
02005             continue;
02006         }
02007 
02008         //
02009         // I have an output pin; loop on every pin on the Downstream Filter
02010         //
02011         while(pDownFilterPin.Release( ), S_OK == pEnumDownFilterPins->Next(1, &pDownFilterPin, &nFetched) )
02012         {
02013             hr = pDownFilterPin->QueryDirection( &pinDir );
02014             if( FAILED( hr ) || PINDIR_OUTPUT == pinDir )
02015             {
02016                 continue;
02017             }
02018 
02019             // Try to connect them and exit if u can else loop more until you can
02020             if(SUCCEEDED(graph_->ConnectDirect(pUpFilterPin, pDownFilterPin, NULL)))
02021             {
02022                 bConnected = TRUE;
02023                 break;
02024             }
02025         }
02026 
02027         hr = pEnumDownFilterPins->Reset();
02028         if( FAILED( hr ) )
02029         {
02030             return hr;
02031         }
02032     }
02033 
02034     if( !bConnected )
02035     {
02036         return E_FAIL;
02037     }
02038 
02039     return S_OK;
02040 }
02041 
02042 
02043 HRESULT
02044 ISampleCaptureGraphBuilder::ConnectPin(
02045                     CComPtr<IPin> pPin,
02046                     CComPtr< IBaseFilter > pDownFilter )
02047 {
02048     if( !pPin || !pDownFilter )
02049     {
02050         return E_INVALIDARG;
02051     }
02052 
02053     PIN_DIRECTION   pinDirection;
02054     HRESULT hr = pPin->QueryDirection( &pinDirection );
02055     if( FAILED( hr ) || PINDIR_INPUT == pinDirection )
02056     {
02057         return E_FAIL;
02058     }
02059 
02060     //
02061     //  Add the filter to the graph
02062     //
02063     BOOL bConnected = FALSE;
02064     ULONG nFetched = 0;
02065     CComPtr<IPin> pDownFilterPin;
02066 
02067     //
02068     //  Loop through every input pin from downstream filter
02069     //  and try to connect the pin
02070     //
02071     CComPtr< IEnumPins > pEnumDownFilterPins;
02072     hr= pDownFilter->EnumPins( &pEnumDownFilterPins );
02073     if( FAILED( hr ) )
02074     {
02075         return hr;
02076     }
02077 
02078     while(pDownFilterPin.Release( ), S_OK == pEnumDownFilterPins->Next(1, &pDownFilterPin, &nFetched) )
02079     {
02080         hr = pDownFilterPin->QueryDirection( &pinDirection );
02081         if( FAILED( hr ) )
02082         {
02083             continue;
02084         }
02085         if( PINDIR_OUTPUT == pinDirection )
02086         {
02087             continue;
02088         }
02089 
02090         hr = graph_->ConnectDirect(pPin, pDownFilterPin, NULL);
02091         if(SUCCEEDED(hr))
02092         {
02093             bConnected = TRUE;
02094             break;
02095         }
02096     }
02097 
02098     if( !bConnected )
02099     {
02100         graph_->RemoveFilter( pDownFilter );
02101         return E_FAIL;
02102     }
02103 
02104     return S_OK;
02105 }
02106 
02110 //include "SampleGrabber.h"
02111 class SampleGrabberCB : public ISampleGrabberCB
02112  {
02113 
02114         public:
02115 
02116                 // These will get set by the main thread below. We need to
02117                 // know this in order to write out the bmp
02118                 long bufferSize;
02119                 unsigned char *buffer;
02120                 int frameId;
02121                 bool frameWanted;
02122                 HANDLE event;
02123 
02124                 // Fake out any COM ref counting
02125                 //
02126                 STDMETHODIMP_(ULONG) AddRef() { return 2; }
02127                 STDMETHODIMP_(ULONG) Release() { return 1; }
02128 
02129                 // Fake out any COM QI'ing
02130                 //
02131                 STDMETHODIMP QueryInterface(REFIID riid, void ** ppv)
02132                  {
02133                         if (!ppv) return E_POINTER;
02134 
02135                         if( riid == IID_ISampleGrabberCB || riid == IID_IUnknown )
02136                          {
02137                                 *ppv = (void *) static_cast<ISampleGrabberCB*> ( this );
02138                                 return NOERROR;
02139                          }
02140 
02141                         return E_NOINTERFACE;
02142                  }
02143 
02144 
02145                 // We don't implement this one
02146                 //
02147                 STDMETHODIMP SampleCB( double SampleTime, IMediaSample * pSample )
02148                  {
02149                         return 0;
02150                  }
02151 
02152 
02153                 // The sample grabber is calling us back on its deliver thread.
02154                 // This is NOT the main app thread!
02155                 //
02156                 STDMETHODIMP BufferCB( double SampleTime, BYTE * pBuffer, long realBufferSize )
02157                  {
02158                         //frameId++;
02159                         if ( !frameWanted )
02160                                 return 0;
02161 
02162                         if (realBufferSize > bufferSize)
02163                          {
02164                                 fprintf(stderr, __FILE__ ": error ! image size too big !!\n");
02165                                 return 0;
02166                          }
02167 
02168                         memcpy(buffer, pBuffer, bufferSize);
02169 
02170                         frameWanted=false;
02171 
02172                         SetEvent(event);
02173 
02174                         return 0;
02175                  }
02176  };
02177 
02178 
02179 
02180 
02181 
02182 
02183 
02184 
02185 
02186 
02187 
02188 
02189 
02190 
02200 
02201 
02202 
02203 
02204 
02205 
02206 
02207 
02208 
02209 
02210 
02211 
02212 
02213 
02214 
02215 
02216 
02217 
02218 
02219 
02220 
02221 
02222 //------------------------------------------------------------------------------
02223 // Macros
02224 //------------------------------------------------------------------------------
02225 #define ABS(x) (((x) > 0) ? (x) : -(x))
02226 
02227 
02228 // Macros
02229 #define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
02230 
02231 
02232 
02233 
02234 // An application can advertise the existence of its filter graph
02235 // by registering the graph with a global Running Object Table (ROT).
02236 // The GraphEdit application can detect and remotely view the running
02237 // filter graph, allowing you to 'spy' on the graph with GraphEdit.
02238 //
02239 // To enable registration in this sample, define REGISTER_FILTERGRAPH.
02240 //
02241 #ifdef  DEBUG
02242 #define REGISTER_FILTERGRAPH
02243 #endif
02244 
02245 
02246 //------------------------------------------------------------------------------
02247 // Global data
02248 //------------------------------------------------------------------------------
02249 
02250 HDEVNOTIFY ghDevNotify=0;
02251 
02252 PUnregisterDeviceNotification gpUnregisterDeviceNotification=0;
02253 PRegisterDeviceNotification gpRegisterDeviceNotification=0;
02254 
02255 
02256 
02257 struct vetDXCapture2
02258 {
02259     HWND ghwndApp;
02260 
02261     TCHAR szCaptureFile[_MAX_PATH];
02262     WORD wCapFileSize;  // size in Meg
02263     ISampleCaptureGraphBuilder *pBuilder;
02264     IVideoWindow *pVW;
02265     IMediaEventEx *pME;
02266     IAMDroppedFrames *pDF;
02267     IAMVideoCompression *pVC;
02268     IAMVfwCaptureDialogs *pDlg;
02269     IAMStreamConfig *pASC;      // for audio cap
02270     IAMStreamConfig *pVSC;      // for video cap
02271     IBaseFilter *pRender;
02272     IBaseFilter *pVCap, *pACap;
02273     IGraphBuilder *pFg;
02274     IFileSinkFilter *pSink;
02275     IConfigAviMux *pConfigAviMux;
02276 
02277     ISampleGrabber* pSampleGrabber;
02278         IBaseFilter* pGrabberBaseFilter;
02279         bool GrabbingEnabled;
02280         SampleGrabberCB* pCallbackGrabber;
02281         IBaseFilter* null_filter;
02282         IBaseFilter* pSmartTeeFilter;
02283 
02284         IMediaControl* pMC; // not used now
02285 
02286     int  iMasterStream;
02287     bool fCaptureGraphBuilt;
02288     bool fPreviewGraphBuilt;
02289     bool fCapturing;
02290     bool fPreviewing;
02291     bool fMPEG2;
02292     bool fCapAudio;
02293     bool fCapCC;
02294     bool fCCAvail;
02295     bool fCapAudioIsRelevant;
02296 
02297     IMoniker *rgpmVideoMenu[10];
02298     IMoniker *rgpmAudioMenu[10];
02299     IMoniker *pmVideo;
02300     IMoniker *pmAudio;
02301 
02302         int pmAudioIndex;
02303         int pmVideoIndex;
02304 
02305     double FrameRate;
02306     bool fWantPreview;
02307     long lCapStartTime;
02308     long lCapStopTime;
02309     WCHAR wachVideoFriendlyName[256];
02310         WCHAR wachAudioFriendlyName[256];
02311     bool fUseTimeLimit;
02312     bool fUseFrameRate;
02313     DWORD dwTimeLimit;
02314     int iFormatDialogPos;
02315     int iSourceDialogPos;
02316     int iDisplayDialogPos;
02317     int iVCapDialogPos;
02318     int iVCrossbarDialogPos;
02319     int iTVTunerDialogPos;
02320     int iACapDialogPos;
02321     int iACrossbarDialogPos;
02322     int iTVAudioDialogPos;
02323     int iVCapCapturePinDialogPos;
02324     int iVCapPreviewPinDialogPos;
02325     int iACapCapturePinDialogPos;
02326     long lDroppedBase;
02327     long lNotBase;
02328     long lDroppedCurrent;
02329     long lNotCurrent;
02330         long lAvgFrameSizeCurrent;
02331     double flFrameCurrent;     // acheived frame rate
02332     long lDataCurrent;         // acheived data rate
02333 
02334     bool fPreviewFaked;
02335 //    CCrossbar *pCrossbar;
02336     int iVideoInputMenuPos;
02337     LONG NumberOfVideoInputs;
02338 
02339     int iNumVCapDevices;
02340     int iNumACapDevices;
02341 
02342     bool displayErrorMessages;
02343     bool autoUpdateWindow;
02344 
02345         vetDirectXInput2::FORMAT_CSP format_CSP;
02346 
02347     DWORD VideoBitRate;
02348     DWORD AudioBitRate;
02349 };
02350 
02351 
02352 
02353 
02354 //------------------------------------------------------------------------------
02355 // Function Prototypes
02356 //------------------------------------------------------------------------------
02357 typedef LONG(PASCAL *LPWNDPROC)(HWND, UINT, WPARAM, LPARAM); // pointer to a window procedure
02358 
02359 /*
02360 int FAR PASCAL AllocCapFileProc(HWND hDlg, UINT Message, UINT wParam, LONG lParam);
02361 int FAR PASCAL FrameRateProc(HWND hDlg, UINT Message, UINT wParam, LONG lParam);
02362 int FAR PASCAL TimeLimitProc(HWND hDlg, UINT Message, UINT wParam, LONG lParam);
02363 int FAR PASCAL PressAKeyProc(HWND hDlg, UINT Message, UINT wParam, LONG lParam);
02364 */
02365 
02366 
02367 
02368 
02369 
02370 
02371 
02372 //
02373 // This function can be used when loading libraries in the Windows System
02374 // folder.  It queries for the system folder and prepends the path to the
02375 // name of the target library.  This helps to prevent spoofing of system DLLs.
02376 //
02377 // NOTE: Using this function may break apps who use Windows Fusion or who
02378 // explicitly replace Windows DLLs in the application's local folder.
02379 // If security is paramount, you can use this as a replacement for LoadLibrary().
02380 //
02381 static HMODULE UtilLoadLibrary(LPCTSTR lpFileName);
02382 
02383 
02384 static DWORDLONG GetSize(LPCTSTR tach);
02385 
02386 void ErrMsg(HWND ghwndApp, bool show, LPTSTR szFormat,...);
02387 
02388 static long GetFreeDiskSpaceInKB(LPTSTR pFile);
02389 
02390 void IMonRelease(IMoniker *&pm);
02391 
02392 void NukeDownstream(vetDXCapture2* cCap, IBaseFilter *pf);
02393 
02394 
02395                 // Adds/removes a DirectShow filter graph from the Running Object Table,
02396                 // allowing GraphEdit to "spy" on a remote filter graph if enabled.
02397 HRESULT AddGraphToRot(IUnknown *pUnkGraph, DWORD *pdwRegister);
02398 
02399 
02400 
02401 static char* Wide2Char(WCHAR* wstr);
02402 
02403 
02404 static void ResizeWindow(HWND ghwndApp, int w, int h);
02405 
02406 
02407 
02408 
02409 // make sure the preview window inside our window is as big as the
02410 // dimensions of captured video, or some capture cards won't show a preview.
02411 // (Also, it helps people tell what size video they're capturing)
02412 // We will resize our app's window big enough so that once the status bar
02413 // is positioned at the bottom there will be enough room for the preview
02414 // window to be w x h
02415 //
02416 int gnRecurse = 0;
02417 
02418 
02419 
02420 
02421 
02422 
02423 
02424 
02425 
02426 
02427 
02431 
02432 
02433 
02434 vetDirectXInput2::vetDirectXInput2(int device)
02435  {
02436 
02437         CoInitialize(NULL);
02438 
02439         g_dwGraphRegister = 0;
02440 
02441         cCap = (vetDXCapture2*)malloc(sizeof(vetDXCapture2));
02442         memset(cCap, 0, sizeof(vetDXCapture2));
02443 
02444 
02445         cCap->ghwndApp = 0;
02446 
02447     cCap->fCapAudio = TRUE;
02448     cCap->fCapCC    = FALSE;
02449         cCap->fCapAudioIsRelevant = FALSE;
02450 
02451         cCap->fCapturing = FALSE;
02452         cCap->fPreviewing = FALSE;
02453         cCap->fWantPreview = FALSE;
02454     cCap->iMasterStream = 1;
02455     cCap->GrabbingEnabled = false;
02456 
02457         cCap->pmAudioIndex = -1;
02458         cCap->pmVideoIndex = -1;
02459 
02460     ZeroMemory(cCap->rgpmAudioMenu, sizeof(cCap->rgpmAudioMenu));
02461     ZeroMemory(cCap->rgpmVideoMenu, sizeof(cCap->rgpmVideoMenu));
02462     cCap->pmVideo = 0;
02463     cCap->pmAudio = 0;
02464     cCap->fMPEG2  = FALSE;
02465         cCap->fPreviewFaked = FALSE;
02466 
02467         cCap->wCapFileSize = 10; // 10 mb
02468 
02469     // get the frame rate from win.ini before making the graph
02470         cCap->fUseFrameRate = TRUE;
02471 
02472     int units_per_frame = 666667;  // 15fps
02473     cCap->FrameRate = 10000000. / units_per_frame;
02474     cCap->FrameRate = (int)(cCap->FrameRate * 100) / 100.;
02475 
02476     // reasonable default
02477         cCap->FrameRate = 15.0;
02478 
02479     cCap->fUseTimeLimit = 0;
02480     cCap->dwTimeLimit   = 100;
02481 
02482 
02483     cCap->iNumVCapDevices = 0;
02484     cCap->iNumACapDevices = 0;
02485 
02486         cCap->displayErrorMessages = true;
02487         cCap->autoUpdateWindow = true;
02488 
02489         width = 0;
02490         height = 0;
02491 
02492  }
02493 
02494 
02495 vetDirectXInput2::~vetDirectXInput2()
02496  {
02497 
02498         Close();
02499 
02500     // Unregister device notifications
02501     if(ghDevNotify != NULL)
02502     {
02503         ASSERT(gpUnregisterDeviceNotification);
02504         gpUnregisterDeviceNotification(ghDevNotify);
02505         ghDevNotify = NULL;
02506     }
02507 
02508         IMonRelease(cCap->pmVideo);
02509         IMonRelease(cCap->pmAudio);
02510 
02511         for(int i = 0; i < NUMELMS(cCap->rgpmVideoMenu); i++)
02512          {
02513                 IMonRelease(cCap->rgpmVideoMenu[i]);
02514          }
02515 
02516         for(i = 0; i < NUMELMS(cCap->rgpmAudioMenu); i++)
02517          {
02518                 IMonRelease(cCap->rgpmAudioMenu[i]);
02519          }
02520 
02521 
02522         delete cCap;
02523 
02524 
02525         CoUninitialize( );
02526  }
02527 
02528 
02529 
02530 
02532 
02533 
02534 void vetDirectXInput2::Close()
02535 {
02536 
02537     if(cCap->fPreviewing)
02538         StopPreview();
02539 
02540     if(cCap->fCapturing)
02541             StopCapture();
02542 
02543 
02544     // Destroy the filter graph and cleanup
02545     TearDownGraph();
02546     FreeCapFilters();
02547 
02548 }
02549 
02550 
02551 
02553 
02554 
02555 // Make a graph builder object we can use for capture graph building
02556 //
02557 int vetDirectXInput2::MakeBuilder()
02558  {
02559     // we have one already
02560     if(cCap->pBuilder)
02561         return VETRET_OK;
02562 
02563     cCap->pBuilder = new ISampleCaptureGraphBuilder( );
02564 
02565     if( cCap->pBuilder == NULL )
02566      {
02567                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error: Cannot create capture Graph Builder (SampleCGB)"));
02568                 return VETRET_INTERNAL_ERR;
02569          }
02570 
02571     return VETRET_OK;
02572  }
02573 
02575 // Make a graph object we can use for capture graph building
02576 //
02577 int vetDirectXInput2::MakeGraph()
02578  {
02579     // we have one already
02580     if(cCap->pFg)
02581         return VETRET_OK;
02582 
02583     HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
02584                                   IID_IGraphBuilder, (LPVOID *)&cCap->pFg);
02585 
02586         if ( hr == NOERROR )
02587                 return VETRET_OK;
02588 
02589         else if ( hr == E_NOINTERFACE )
02590          {
02591                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error: Cannot find filter IID_IGraphBuilder.\r\nIs DirectX installed and running?"));
02592                 return VETRET_INTERNAL_ERR;
02593          }
02594 
02595         return VETRET_OK;
02596  }
02597 
02598 
02599 
02602 
02603 
02604 
02605 // Tear down everything downstream of the capture filters, so we can build
02606 // a different capture graph.  Notice that we never destroy the capture filters
02607 // and WDM filters upstream of them, because then all the capture settings
02608 // we've set would be lost.
02609 //
02610 void vetDirectXInput2::TearDownGraph()
02611 {
02612     SAFE_RELEASE(cCap->pSink);
02613     SAFE_RELEASE(cCap->pConfigAviMux);
02614     SAFE_RELEASE(cCap->pRender);
02615     SAFE_RELEASE(cCap->pME);
02616     SAFE_RELEASE(cCap->pDF);
02617 
02618     if(cCap->pVW)
02619     {
02620         // stop drawing in our window, or we may get wierd repaint effects
02621         cCap->pVW->put_Owner(NULL);
02622         cCap->pVW->put_Visible(OAFALSE);
02623         cCap->pVW->Release();
02624         cCap->pVW = NULL;
02625     }
02626 
02627     // destroy the graph downstream of our capture filters
02628     if(cCap->pVCap)
02629         NukeDownstream(cCap, cCap->pVCap);
02630     if(cCap->pACap)
02631         NukeDownstream(cCap, cCap->pACap);
02632     if(cCap->pVCap)
02633         cCap->pBuilder->ReleaseFilters();
02634 
02635     // potential debug output - what the graph looks like
02636     // if (cCap->pFg) DumpGraph(cCap->pFg, 1);
02637 
02638 #ifdef REGISTER_FILTERGRAPH
02639     // Remove filter graph from the running object table
02640     if(g_dwGraphRegister)
02641     {
02642         RemoveGraphFromRot(g_dwGraphRegister);
02643         g_dwGraphRegister = 0;
02644     }
02645 #endif
02646 
02647     cCap->fCaptureGraphBuilt = FALSE;
02648     cCap->fPreviewGraphBuilt = FALSE;
02649     cCap->fPreviewFaked = FALSE;
02650 }
02651 
02652 
02654 
02655 
02656 
02657 // Removes a filter graph from the Running Object Table
02658 int vetDirectXInput2::RemoveGraphFromRot(DWORD pdwRegister)
02659  {
02660         IRunningObjectTable *pROT;
02661 
02662         if( SUCCEEDED(GetRunningObjectTable(0, &pROT)) )
02663          {
02664                 pROT->Revoke(pdwRegister);
02665                 pROT->Release();
02666                 return VETRET_OK;
02667          }
02668 
02669         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error: Falied to remove graph from the Running Object Table.\r\nCan't get current ROT."));
02670         return VETRET_INTERNAL_ERR;
02671  }
02672 
02673 
02675 
02676 
02677 
02678 
02679 
02680 
02682 
02683 
02684 // Adds a DirectShow filter graph to the Running Object Table,
02685 // allowing GraphEdit to "spy" on a remote filter graph.
02686 HRESULT AddGraphToRot(IUnknown *pUnkGraph, DWORD *pdwRegister)
02687  {
02688         IMoniker * pMoniker;
02689         IRunningObjectTable *pROT;
02690         WCHAR wsz[128];
02691         HRESULT hr;
02692 
02693         if (!pUnkGraph || !pdwRegister)
02694                 return E_POINTER;
02695 
02696         if(FAILED(GetRunningObjectTable(0, &pROT)))
02697                 return E_FAIL;
02698 
02699         wsprintfW( wsz, L"FilterGraph %08x pid %08x\0", (DWORD_PTR)pUnkGraph, GetCurrentProcessId() );
02700 
02701         hr = CreateItemMoniker(L"!", wsz, &pMoniker);
02702         if( SUCCEEDED(hr) )
02703          {
02704                 // Use the ROTFLAGS_REGISTRATIONKEEPSALIVE to ensure a strong reference
02705                 // to the object.  Using this flag will cause the object to remain
02706                 // registered until it is explicitly revoked with the Revoke() method.
02707                 //
02708                 // Not using this flag means that if GraphEdit remotely connects
02709                 // to this graph and then GraphEdit exits, this object registration
02710                 // will be deleted, causing future attempts by GraphEdit to fail until
02711                 // this application is restarted or until the graph is registered again.
02712                 hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pUnkGraph, pMoniker, pdwRegister);
02713                 pMoniker->Release();
02714          }
02715 
02716         pROT->Release();
02717         return hr;
02718  }
02719 
02720 
02721 
02722 
02723 
02724 
02725 
02726 
02727 
02728 
02729 
02730 
02731 
02732 
02733 
02737 
02738 // create the capture filters of the graph.  We need to keep them loaded from
02739 // the beginning, so we can set parameters on them and have them remembered
02740 //
02741 int vetDirectXInput2::InitCapFilters()
02742 {
02743         HRESULT hr=S_OK;
02744 
02745         cCap->fCCAvail = FALSE;  // assume no closed captioning support
02746 
02747         if( MakeBuilder() )
02748          {
02749                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Cannot instantiate graph builder"));
02750                 return VETRET_INTERNAL_ERR;
02751          }
02752 
02753         //
02754         // First, we need a Video Capture filter, and some interfaces
02755         //
02756         cCap->pVCap = NULL;
02757 
02758     if(cCap->pmVideo != 0)
02759     {
02760         IPropertyBag *pBag;
02761         cCap->wachVideoFriendlyName[0] = 0;
02762 
02763         hr = cCap->pmVideo->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
02764         if(SUCCEEDED(hr))
02765         {
02766             VARIANT var;
02767             var.vt = VT_BSTR;
02768 
02769             hr = pBag->Read(L"FriendlyName", &var, NULL);
02770             if(hr == NOERROR)
02771             {
02772                 lstrcpyW(cCap->wachVideoFriendlyName, var.bstrVal);
02773                 SysFreeString(var.bstrVal);
02774             }
02775 
02776             pBag->Release();
02777         }
02778 
02779         hr = cCap->pmVideo->BindToObject(0, 0, IID_IBaseFilter, (void**)&cCap->pVCap);
02780     }
02781 
02782         if(cCap->pVCap == NULL)
02783          {
02784                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error %x: Cannot create video capture filter"), hr);
02785                 goto InitCapFiltersFail;
02786          }
02787 
02788         //
02789         // make a filtergraph, give it to the graph builder and put the video
02790         // capture filter in the graph
02791         //
02792 
02793         if( MakeGraph() )
02794          {
02795                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Cannot instantiate filtergraph"));
02796                 goto InitCapFiltersFail;
02797          }
02798 
02799         hr = cCap->pBuilder->SetFiltergraph(cCap->pFg);
02800         if(hr != NOERROR)
02801          {
02802                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Cannot give graph to builder"));
02803                 goto InitCapFiltersFail;
02804          }
02805 
02806         // Add the video capture filter to the graph with its friendly name
02807         hr = cCap->pFg->AddFilter(cCap->pVCap, cCap->wachVideoFriendlyName);
02808         if(hr != NOERROR)
02809          {
02810                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error %x: Cannot add vidcap to filtergraph"), hr);
02811                 goto InitCapFiltersFail;
02812          }
02813 
02814         // Calling FindInterface below will result in building the upstream
02815         // section of the capture graph (any WDM TVTuners or Crossbars we might
02816         // need).
02817 
02818         // we use this interface to get the name of the driver
02819         // Don't worry if it doesn't work:  This interface may not be available
02820         // until the pin is connected, or it may not be available at all.
02821         // (eg: interface may not be available for some DV capture)
02822     hr = cCap->pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
02823                                       &MEDIATYPE_Interleaved, cCap->pVCap,
02824                                       IID_IAMVideoCompression, (void **)&cCap->pVC);
02825     if(hr != S_OK)
02826     {
02827         hr = cCap->pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
02828                                           &MEDIATYPE_Video, cCap->pVCap,
02829                                           IID_IAMVideoCompression, (void **)&cCap->pVC);
02830     }
02831 
02832     // !!! What if this interface isn't supported?
02833     // we use this interface to set the frame rate and get the capture size
02834     hr = cCap->pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
02835                                       &MEDIATYPE_Interleaved,
02836                                       cCap->pVCap, IID_IAMStreamConfig, (void **)&cCap->pVSC);
02837 
02838     if(hr != NOERROR)
02839     {
02840         hr = cCap->pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
02841                                           &MEDIATYPE_Video, cCap->pVCap,
02842                                           IID_IAMStreamConfig, (void **)&cCap->pVSC);
02843         if(hr != NOERROR)
02844         {
02845             // this means we can't set frame rate (non-DV only)
02846             ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error %x: Cannot find VCapture:IAMStreamConfig"), hr);
02847         }
02848     }
02849 
02850     cCap->fCapAudioIsRelevant = TRUE;
02851 
02852     AM_MEDIA_TYPE *pmt;
02853 
02854     // default capture format
02855     if(cCap->pVSC && cCap->pVSC->GetFormat(&pmt) == S_OK)
02856     {
02857         // DV capture does not use a VIDEOINFOHEADER
02858         if(pmt->formattype == FORMAT_VideoInfo)
02859         {
02860 
02861                         width = HEADER(pmt->pbFormat)->biWidth;
02862                         height = abs(HEADER(pmt->pbFormat)->biHeight);
02863 
02864 //TODO                  cCap->VideoBitRate = HEADER(pmt->pbFormat)->biWidth;
02865 
02866             // resize our window to the default capture size
02867                         if ( cCap->autoUpdateWindow )
02868                                 ResizeWindow(cCap->ghwndApp, width, height);
02869 
02870         }
02871         if(pmt->majortype != MEDIATYPE_Video)
02872         {
02873             // This capture filter captures something other that pure video.
02874             // Maybe it's DV or something?  Anyway, chances are we shouldn't
02875             // allow capturing audio separately, since our video capture
02876             // filter may have audio combined in it already!
02877             cCap->fCapAudioIsRelevant = FALSE;
02878             cCap->fCapAudio = FALSE;
02879         }
02880 
02881         if (pmt->subtype == MEDIASUBTYPE_RGB24)
02882          {
02883                         cCap->format_CSP = VETFRAMET_CS_RGB;
02884                  }
02885 
02886         DeleteMediaType(pmt);
02887     }
02888 
02889     // we use this interface to bring up the 3 dialogs
02890     // NOTE:  Only the VfW capture filter supports this.  This app only brings
02891     // up dialogs for legacy VfW capture drivers, since only those have dialogs
02892     hr = cCap->pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
02893                                       &MEDIATYPE_Video, cCap->pVCap,
02894                                       IID_IAMVfwCaptureDialogs, (void **)&cCap->pDlg);
02895 
02896     // Use the crossbar class to help us sort out all the possible video inputs
02897     // The class needs to be given the capture filters ANALOGVIDEO input pin
02898     {
02899         IPin        *pP = 0;
02900         IEnumPins   *pins=0;
02901         ULONG        n;
02902         PIN_INFO     pinInfo;
02903         bool         Found = false;
02904         IKsPropertySet *pKs=0;
02905         GUID guid;
02906         DWORD dw;
02907         bool fMatch = false;
02908 
02909 //        cCap->pCrossbar = NULL;
02910 
02911         if(SUCCEEDED(cCap->pVCap->EnumPins(&pins)))
02912         {
02913             while(!Found && (S_OK == pins->Next(1, &pP, &n)))
02914             {
02915                 if(S_OK == pP->QueryPinInfo(&pinInfo))
02916                 {
02917                     if(pinInfo.dir == PINDIR_INPUT)
02918                     {
02919                         // is this pin an ANALOGVIDEOIN input pin?
02920                         if(pP->QueryInterface(IID_IKsPropertySet,
02921                             (void **)&pKs) == S_OK)
02922                         {
02923                             if(pKs->Get(AMPROPSETID_Pin,
02924                                 AMPROPERTY_PIN_CATEGORY, NULL, 0,
02925                                 &guid, sizeof(GUID), &dw) == S_OK)
02926                             {
02927                                 if(guid == PIN_CATEGORY_ANALOGVIDEOIN)
02928                                     fMatch = TRUE;
02929                             }
02930                             pKs->Release();
02931                         }
02932 
02933                         if(fMatch)
02934                         {
02935                             HRESULT hrCreate=S_OK;
02936 //                            cCap->pCrossbar = new CCrossbar(pP, &hrCreate);
02937   //                          if (!cCap->pCrossbar || FAILED(hrCreate))
02938                                 break;
02939 
02940 //                            hr = cCap->pCrossbar->GetInputCount(&cCap->NumberOfVideoInputs);
02941                             Found = TRUE;
02942                         }
02943                     }
02944                     pinInfo.pFilter->Release();
02945                 }
02946                 pP->Release();
02947             }
02948             pins->Release();
02949         }
02950     }
02951 
02952         cCap->wachAudioFriendlyName[0] = 0;
02953 
02954     // there's no point making an audio capture filter
02955     if(cCap->fCapAudioIsRelevant == FALSE)
02956         goto SkipAudio;
02957 
02958     // create the audio capture filter, even if we are not capturing audio right
02959     // now, so we have all the filters around all the time.
02960 
02961     //
02962     // We want an audio capture filter and some interfaces
02963     //
02964 
02965     if(cCap->pmAudio == 0)
02966     {
02967         // there are no audio capture devices. We'll only allow video capture
02968         cCap->fCapAudio = FALSE;
02969         goto SkipAudio;
02970     }
02971     cCap->pACap = NULL;
02972 
02973 
02974     hr = cCap->pmAudio->BindToObject(0, 0, IID_IBaseFilter, (void**)&cCap->pACap);
02975 
02976     if(cCap->pACap == NULL)
02977     {
02978         // there are no audio capture devices. We'll only allow video capture
02979         cCap->fCapAudio = FALSE;
02980         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Cannot create audio capture filter"));
02981         goto SkipAudio;
02982     }
02983 
02984     //
02985     // put the audio capture filter in the graph
02986     //
02987     {
02988         IPropertyBag *pBag;
02989 
02990         cCap->wachAudioFriendlyName[0] = 0;
02991 
02992         // Read the friendly name of the filter to assist with remote graph
02993         // viewing through GraphEdit
02994         hr = cCap->pmAudio->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
02995         if(SUCCEEDED(hr))
02996         {
02997             VARIANT var;
02998             var.vt = VT_BSTR;
02999 
03000             hr = pBag->Read(L"FriendlyName", &var, NULL);
03001             if(hr == NOERROR)
03002             {
03003                 lstrcpyW(cCap->wachAudioFriendlyName, var.bstrVal);
03004                 SysFreeString(var.bstrVal);
03005             }
03006 
03007             pBag->Release();
03008         }
03009 
03010         // We'll need this in the graph to get audio property pages
03011         hr = cCap->pFg->AddFilter(cCap->pACap, cCap->wachAudioFriendlyName);
03012         if(hr != NOERROR)
03013         {
03014             ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error %x: Cannot add audio capture filter to filtergraph"), hr);
03015             goto InitCapFiltersFail;
03016         }
03017     }
03018 
03019     // Calling FindInterface below will result in building the upstream
03020     // section of the capture graph (any WDM TVAudio's or Crossbars we might
03021     // need).
03022 
03023     // !!! What if this interface isn't supported?
03024     // we use this interface to set the captured wave format
03025     hr = cCap->pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, cCap->pACap,
03026                                       IID_IAMStreamConfig, (void **)&cCap->pASC);
03027 
03028     if(hr != NOERROR)
03029     {
03030         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Cannot find ACapture:IAMStreamConfig"));
03031     }
03032 
03033 SkipAudio:
03034 
03035     // Can this filter do closed captioning?
03036     IPin *pPin;
03037     hr = cCap->pBuilder->FindPin(cCap->pVCap, PINDIR_OUTPUT, &PIN_CATEGORY_VBI,
03038                                 NULL, FALSE, 0, &pPin);
03039     if(hr != S_OK)
03040         hr = cCap->pBuilder->FindPin(cCap->pVCap, PINDIR_OUTPUT, &PIN_CATEGORY_CC,
03041                                     NULL, FALSE, 0, &pPin);
03042     if(hr == S_OK)
03043     {
03044         pPin->Release();
03045         cCap->fCCAvail = TRUE;
03046     }
03047     else
03048     {
03049         cCap->fCapCC = FALSE;    // can't capture it, then
03050     }
03051 
03052     // potential debug output - what the graph looks like
03053     // DumpGraph(cCap->pFg, 1);
03054 
03055     return VETRET_OK;
03056 
03057 InitCapFiltersFail:
03058     FreeCapFilters();
03059     return VETRET_INTERNAL_ERR;
03060 }
03061 
03064 
03065 // all done with the capture filters and the graph builder
03066 //
03067 void vetDirectXInput2::FreeCapFilters()
03068  {
03069         SAFE_RELEASE(cCap->pFg);
03070 
03071         if( cCap->pBuilder )
03072          {
03073                 delete cCap->pBuilder;
03074                 cCap->pBuilder = NULL;
03075          }
03076 
03077         SAFE_RELEASE(cCap->pVCap);
03078         SAFE_RELEASE(cCap->pACap);
03079         SAFE_RELEASE(cCap->pASC);
03080         SAFE_RELEASE(cCap->pVSC);
03081         SAFE_RELEASE(cCap->pVC);
03082         SAFE_RELEASE(cCap->pDlg);
03083 
03084         SAFE_RELEASE(cCap->pGrabberBaseFilter);
03085 
03086         SAFE_RELEASE(cCap->pCallbackGrabber);
03087 
03088         SAFE_RELEASE(cCap->pSmartTeeFilter);
03089 
03090  }
03091 
03094 
03095 // build the capture graph
03096 //
03097 int vetDirectXInput2::BuildCaptureGraph()
03098 {
03099     USES_CONVERSION;
03100 
03101         HRESULT hr;
03102     AM_MEDIA_TYPE *pmt=0;
03103 
03104     // we have one already
03105     if(cCap->fCaptureGraphBuilt)
03106         return VETRET_OK; // mmh bad
03107 
03108     // No rebuilding while we're running
03109     if(cCap->fCapturing || cCap->fPreviewing)
03110         return VETRET_ILLEGAL_USE;
03111 
03112     // We don't have the necessary capture filters
03113     if(cCap->pVCap == NULL)
03114         return VETRET_ILLEGAL_USE;
03115     if(cCap->pACap == NULL && cCap->fCapAudio)
03116         return VETRET_ILLEGAL_USE;
03117 
03118     // we already have another graph built... tear down the old one
03119     if( cCap->fPreviewGraphBuilt )
03120         TearDownGraph();
03121 
03122     //
03123     // We need a rendering section that will write the capture file out in AVI
03124     // file format
03125     //
03126 
03127     GUID guid;
03128     if( cCap->fMPEG2 )
03129     {
03130         guid = MEDIASUBTYPE_Mpeg2;
03131     }
03132     else
03133     {
03134         guid = MEDIASUBTYPE_Avi;
03135     }
03136 
03137     hr = cCap->pBuilder->SetOutputFileName(&guid, T2W(cCap->szCaptureFile),
03138                                           &cCap->pRender, &cCap->pSink);
03139     if(hr != NOERROR)
03140     {
03141                 if (hr == E_FAIL)
03142                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("FAILIED: Setting file name\r\nFailure."));
03143                 else if (hr == E_INVALIDARG)
03144                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("FAILIED: Setting file name\r\nAVI is the only supported output format. (try to update directx?)"));
03145                 else if (hr == E_UNEXPECTED)
03146                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("FAILIED: Setting file name\r\nUnexpected error occurred."));
03147                 else if (hr == E_OUTOFMEMORY)
03148                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("FAILIED: Setting file name\r\nOut of Memory."));
03149                 else
03150                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("FAILIED: Setting file name\r\nUnknown ErrorCode."));
03151 
03152         goto SetupCaptureFail;
03153     }
03154 
03155     // Now tell the AVIMUX to write out AVI files that old apps can read properly.
03156     // If we don't, most apps won't be able to tell where the keyframes are,
03157     // slowing down editing considerably
03158     // Doing this will cause one seek (over the area the index will go) when
03159     // you capture past 1 Gig, but that's no big deal.
03160     // NOTE: This is on by default, so it's not necessary to turn it on
03161 
03162     // Also, set the proper MASTER STREAM
03163 
03164     if( !cCap->fMPEG2 )
03165     {
03166         hr = cCap->pRender->QueryInterface(IID_IConfigAviMux, (void **)&cCap->pConfigAviMux);
03167         if(hr == NOERROR && cCap->pConfigAviMux)
03168         {
03169             cCap->pConfigAviMux->SetOutputCompatibilityIndex(TRUE);
03170             if(cCap->fCapAudio)
03171             {
03172                 hr = cCap->pConfigAviMux->SetMasterStream(cCap->iMasterStream);
03173                 if(hr != NOERROR)
03174                     ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("SetMasterStream failed!"));
03175             }
03176         }
03177     }
03178 
03179 
03180 //to add here: cCap->pBuilder->RenderFile(wFile, NULL);
03181 
03182     //
03183     // Render the video capture and preview pins - even if the capture filter only
03184     // has a capture pin (and no preview pin) this should work... because the
03185     // capture graph builder will use a smart tee filter to provide both capture
03186     // and preview.  We don't have to worry.  It will just work.
03187     //
03188 
03189     // NOTE that we try to render the interleaved pin before the video pin, because
03190     // if BOTH exist, it's a DV filter and the only way to get the audio is to use
03191     // the interleaved pin.  Using the Video pin on a DV filter is only useful if
03192     // you don't want the audio.
03193 
03194     if( !cCap->fMPEG2 )
03195     {
03196         hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE,
03197                                          &MEDIATYPE_Interleaved,
03198                                          cCap->pVCap, NULL, cCap->pRender);
03199         if(hr != NOERROR)
03200         {
03201             hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE,
03202                                              &MEDIATYPE_Video,
03203                                              cCap->pVCap, NULL, cCap->pRender);
03204             if(hr != NOERROR)
03205             {
03206                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Cannot render video capture stream"));
03207                 goto SetupCaptureFail;
03208             }
03209         }
03210 
03211         if(cCap->fWantPreview)
03212         {
03213             hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Interleaved,
03214                                             cCap->pVCap, NULL, NULL);
03215             if(hr == VFW_S_NOPREVIEWPIN)
03216             {
03217                 // preview was faked up for us using the (only) capture pin
03218                 cCap->fPreviewFaked = TRUE;
03219             }
03220             else if(hr != S_OK)
03221             {
03222                 hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
03223                                                  cCap->pVCap, NULL, NULL);
03224                 if(hr == VFW_S_NOPREVIEWPIN)
03225                 {
03226                     // preview was faked up for us using the (only) capture pin
03227                     cCap->fPreviewFaked = TRUE;
03228                 }
03229                 else if(hr != S_OK)
03230                 {
03231                     ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Cannot render video preview stream"));
03232                     goto SetupCaptureFail;
03233                 }
03234             }
03235         }
03236     }
03237     else
03238     {
03239         CComPtr< IBaseFilter > sink;
03240         if( &cCap->pSink )
03241         {
03242             cCap->pSink->QueryInterface( IID_IBaseFilter, reinterpret_cast<void **>( &sink ) );
03243         }
03244 
03245         hr = cCap->pBuilder->RenderStream(NULL,
03246                                          &MEDIATYPE_Stream,
03247                                          cCap->pVCap, NULL, sink);
03248     }
03249 
03250     //
03251     // Render the audio capture pin?
03252     //
03253 
03254     if(!cCap->fMPEG2 && cCap->fCapAudio)
03255     {
03256         hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio,
03257                                          cCap->pACap, NULL, cCap->pRender);
03258         if(hr != NOERROR)
03259         {
03260             ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Cannot render audio capture stream"));
03261             goto SetupCaptureFail;
03262         }
03263     }
03264 
03265     //
03266     // Render the closed captioning pin? It could be a CC or a VBI category pin,
03267     // depending on the capture driver
03268     //
03269 
03270     if(!cCap->fMPEG2  && cCap->fCapCC)
03271     {
03272         hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_CC, NULL,
03273                                          cCap->pVCap, NULL, cCap->pRender);
03274         if(hr != NOERROR)
03275         {
03276             hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_VBI, NULL,
03277                                              cCap->pVCap, NULL, cCap->pRender);
03278             if(hr != NOERROR)
03279             {
03280                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Cannot render closed captioning"));
03281                 // so what? goto SetupCaptureFail;
03282             }
03283         }
03284         // To preview and capture VBI at the same time, we can call this twice
03285         if(cCap->fWantPreview)
03286         {
03287             hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_VBI, NULL,
03288                                              cCap->pVCap, NULL, NULL);
03289         }
03290     }
03291 
03292     //
03293     // Get the preview window to be a child of our app's window
03294     //
03295 
03296     // This will find the IVideoWindow interface on the renderer.  It is
03297     // important to ask the filtergraph for this interface... do NOT use
03298     // ICaptureGraphBuilder2::FindInterface, because the filtergraph needs to
03299     // know we own the window so it can give us display changed messages, etc.
03300 
03301     if(!cCap->fMPEG2 && cCap->fWantPreview)
03302     {
03303         hr = cCap->pFg->QueryInterface(IID_IVideoWindow, (void **)&cCap->pVW);
03304         if(hr != NOERROR && cCap->fWantPreview)
03305         {
03306             ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("This graph cannot preview"));
03307         }
03308         else if(hr == NOERROR)
03309         {
03310 //autoUpdateWindow
03311 
03312             RECT rc;
03313             cCap->pVW->put_Owner((OAHWND)cCap->ghwndApp);    // We own the window now
03314             cCap->pVW->put_WindowStyle(WS_CHILD);    // you are now a child
03315 
03316         GetClientRect(cCap->ghwndApp, &rc);
03317 //        cyBorder = GetSystemMetrics(SM_CYBORDER);
03318 //        cy = statusGetHeight() + cyBorder;
03319 //        rc.bottom -= cy;
03320 
03321         cCap->pVW->SetWindowPosition(0, 0, rc.right, rc.bottom); // be this big
03322 
03323             // give the preview window all our space but where the status bar is
03324 //            GetClientRect(cCap->ghwndApp, &rc);
03325 //            cyBorder = GetSystemMetrics(SM_CYBORDER);
03326 //            cy = statusGetHeight() + cyBorder;
03327 //            rc.bottom -= cy;
03328 
03329 //            cCap->pVW->SetWindowPosition(40, 50, rc.right, rc.bottom); // be this big
03330             cCap->pVW->put_Visible(OATRUE);
03331 
03332         }
03333     }
03334 
03335     // now tell it what frame rate to capture at.  Just find the format it
03336     // is capturing with, and leave everything alone but change the frame rate
03337     if( !cCap->fMPEG2 )
03338     {
03339         hr = cCap->fUseFrameRate ? E_FAIL : NOERROR;
03340         if(cCap->pVSC && cCap->fUseFrameRate)
03341         {
03342             hr = cCap->pVSC->GetFormat(&pmt);
03343 
03344             // DV capture does not use a VIDEOINFOHEADER
03345             if(hr == NOERROR)
03346             {
03347                 if(pmt->formattype == FORMAT_VideoInfo)
03348                 {
03349                     VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *)pmt->pbFormat;
03350                     pvi->AvgTimePerFrame = (LONGLONG)(10000000 / cCap->FrameRate);
03351                     hr = cCap->pVSC->SetFormat(pmt);
03352                 }
03353                 DeleteMediaType(pmt);
03354             }
03355         }
03356         if(hr != NOERROR)
03357             ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Cannot set frame rate for capture"));
03358     }
03359 
03360     // now ask the filtergraph to tell us when something is completed or aborted
03361     // (EC_COMPLETE, EC_USERABORT, EC_ERRORABORT).  This is how we will find out
03362     // if the disk gets full while capturing
03363     hr = cCap->pFg->QueryInterface(IID_IMediaEventEx, (void **)&cCap->pME);
03364     if(hr == NOERROR)
03365     {
03367     }
03368 
03369     // potential debug output - what the graph looks like
03370     // DumpGraph(cCap->pFg, 1);
03371 
03372     // Add our graph to the running object table, which will allow
03373     // the GraphEdit application to "spy" on our graph
03374 #ifdef REGISTER_FILTERGRAPH
03375     hr = AddGraphToRot(cCap->pFg, &g_dwGraphRegister);
03376     if(FAILED(hr))
03377     {
03378         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Failed to register filter graph with ROT!  hr=0x%x"), hr);
03379         g_dwGraphRegister = 0;
03380     }
03381 #endif
03382 
03383     // All done.
03384     cCap->fCaptureGraphBuilt = TRUE;
03385     return VETRET_OK;
03386 
03387 SetupCaptureFail:
03388     TearDownGraph();
03389         return VETRET_INTERNAL_ERR;
03390 }
03391 
03392 
03395 
03396 
03397 int vetDirectXInput2::BuildGrabberGraph(bool mpeg2)
03398  {
03399         if ( !cCap->GrabbingEnabled )
03400                 return VETRET_ILLEGAL_USE;
03401 
03402         HRESULT hr;
03403 
03404         if ( !cCap->pCallbackGrabber )
03405          {
03406                 cCap->pCallbackGrabber = new SampleGrabberCB();
03407          }
03408 
03409 
03410         hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
03411                                                         IID_IBaseFilter, (LPVOID *)&cCap->pGrabberBaseFilter);
03412 
03413         if (FAILED(hr))
03414          {
03415                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error %x: Cannot find CLSID_SampleGrabber"), hr);
03416                 cCap->GrabbingEnabled = false;
03417                 return VETRET_INTERNAL_ERR;
03418          }
03419 
03420         cCap->pGrabberBaseFilter->QueryInterface(IID_ISampleGrabber, (void**)&cCap->pSampleGrabber);
03421 
03422         hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER,
03423                                                 IID_IBaseFilter, reinterpret_cast<void**>(&cCap->null_filter));
03424         hr = cCap->pFg->AddFilter(cCap->null_filter,L"Null Renderer");
03425 
03426         if (cCap->pSampleGrabber == NULL)
03427          {
03428         //E_NOINTERFACE;
03429                 cCap->GrabbingEnabled = false;
03430                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error %x: Cannot create grabber"), hr);
03431                 return VETRET_INTERNAL_ERR;
03432          }
03433 
03434 
03435         hr = cCap->pFg->AddFilter(cCap->pGrabberBaseFilter,L"Grabber");
03436         if (FAILED(hr))
03437          {
03438         //E_NOINTERFACE;
03439                 cCap->GrabbingEnabled = false;
03440                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error %x: Cannot Add Grabber to graph."), hr);
03441                 return VETRET_INTERNAL_ERR;
03442          }
03443 
03444 
03445         hr = cCap->pSampleGrabber->SetBufferSamples(FALSE);
03446 
03447         hr = cCap->pSampleGrabber->SetOneShot(FALSE);
03448 
03449         hr = cCap->pSampleGrabber->SetCallback( cCap->pCallbackGrabber, 1);
03450 
03451         AM_MEDIA_TYPE mt;
03452         ZeroMemory(&mt,sizeof(AM_MEDIA_TYPE));
03453 
03454         mt.majortype = MEDIATYPE_Video;
03455         mt.subtype = MEDIASUBTYPE_RGB24;
03456         mt.formattype = FORMAT_VideoInfo;
03457 
03458         hr = cCap->pSampleGrabber->SetMediaType(&mt);
03459         if (FAILED(hr))
03460          {
03461                 cCap->GrabbingEnabled = false;
03462                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error %x: set requested format"), hr);
03463                 return VETRET_INTERNAL_ERR;
03464          }
03465 
03466 
03467         IBaseFilter* pAviDecFilter = NULL;
03468         hr = CoCreateInstance(CLSID_AVIDec, NULL, CLSCTX_INPROC_SERVER,
03469                                                                 IID_IBaseFilter, (LPVOID *)&pAviDecFilter);
03470 
03471         hr = cCap->pFg->AddFilter(pAviDecFilter,L"Avi Decompressor (2)");
03472 
03473         if ( !mpeg2 )   // it's NOT an MPEG2 device
03474          {
03475                 // dshow uses smart tee by itself...
03476 
03477                 hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE,
03478                                                                                          &MEDIATYPE_Video, cCap->pVCap, pAviDecFilter, cCap->pGrabberBaseFilter);
03479 
03480          }
03481         else // MPEG2 device
03482          {
03483                 hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE,
03484                                                                                          NULL, cCap->pSmartTeeFilter, pAviDecFilter, cCap->pGrabberBaseFilter);
03485 
03486 
03487 //              hr = CoCreateInstance(CLSID_SmartTee, NULL, CLSCTX_INPROC_SERVER,
03488 //                                                                      IID_IBaseFilter, (LPVOID *)&cCap->pSmartTeeFilter);
03489 
03490 //              hr = cCap->pFg->AddFilter(cCap->pSmartTeeFilter ,L"Smart Tee (2)");
03491 
03492 //              hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE,
03493 //                                                                              NULL, cCap->pSmartTeeFilter, pAviDecFilter, cCap->pGrabberBaseFilter);
03494 
03495          }
03496 
03497         hr = cCap->pBuilder->RenderStream(NULL,
03498                                                                           NULL, cCap->pGrabberBaseFilter, NULL, cCap->null_filter);
03499 
03500         return VETRET_OK;
03501  }
03502 
03503 
03504 // build the preview graph!
03505 //
03506 // !!! PLEASE NOTE !!!  Some new WDM devices have totally separate capture
03507 // and preview settings.  An application that wishes to preview and then
03508 // capture may have to set the preview pin format using IAMStreamConfig on the
03509 // preview pin, and then again on the capture pin to capture with that format.
03510 // In this sample app, there is a separate page to set the settings on the
03511 // capture pin and one for the preview pin.  To avoid the user
03512 // having to enter the same settings in 2 dialog boxes, an app can have its own
03513 // UI for choosing a format (the possible formats can be enumerated using
03514 // IAMStreamConfig) and then the app can programmatically call IAMStreamConfig
03515 // to set the format on both pins.
03516 //
03517 int vetDirectXInput2::BuildPreviewGraph()
03518 {
03519     HRESULT hr;
03520     AM_MEDIA_TYPE *pmt;
03521 
03522     // we have one already
03523     if(cCap->fPreviewGraphBuilt)
03524         return VETRET_OK;       //mmh bad
03525 
03526     // No rebuilding while we're running
03527     if(cCap->fCapturing || cCap->fPreviewing)
03528         return VETRET_ILLEGAL_USE;
03529 
03530     // We don't have the necessary capture filters
03531     if(cCap->pVCap == NULL)
03532         return VETRET_ILLEGAL_USE;
03533     if(cCap->pACap == NULL && cCap->fCapAudio)
03534         return VETRET_ILLEGAL_USE;
03535 
03536 
03537     // we already have another graph built... tear down the old one
03538     if( cCap->fCaptureGraphBuilt )
03539         TearDownGraph();
03540 
03541     //
03542     // Render the preview pin - even if there is not preview pin, the capture
03543     // graph builder will use a smart tee filter and provide a preview.
03544     //
03545     // !!! what about latency/buffer issues?
03546 
03547     // NOTE that we try to render the interleaved pin before the video pin, because
03548     // if BOTH exist, it's a DV filter and the only way to get the audio is to use
03549     // the interleaved pin.  Using the Video pin on a DV filter is only useful if
03550     // you don't want the audio.
03551 
03552     if( cCap->fMPEG2 )
03553      {
03554                 if ( !cCap->GrabbingEnabled )
03555                  {
03556 
03557                 hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW,
03558                                                  &MEDIATYPE_Stream, cCap->pVCap, NULL, NULL);
03559 
03560                  }
03561                 else
03562                  {
03563 
03564                 hr = CoCreateInstance(CLSID_SmartTee, NULL, CLSCTX_INPROC_SERVER,
03565                                                                         IID_IBaseFilter, (LPVOID *)&cCap->pSmartTeeFilter);
03566 
03567                         hr = cCap->pFg->AddFilter(cCap->pSmartTeeFilter ,L"Smart Tee (GRAB)");
03568 
03569                 hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW,
03570                                                  &MEDIATYPE_Stream, cCap->pVCap, NULL, cCap->pSmartTeeFilter);
03571 
03572                 // video renderer
03573 
03574 
03575 //              hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW,
03576 //                                               NULL, cCap->pSmartTeeFilter, NULL, NULL);
03577 
03578 //                      BuildGrabberGraph(true);
03579                  }
03580 
03581 
03582         if( FAILED( hr ) )
03583         {
03584             ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Cannot build MPEG2 preview graph!"));
03585         }
03586 
03587 
03588      }
03589     else
03590      {
03591                 hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW,
03592                                                                                  &MEDIATYPE_Interleaved, cCap->pVCap, NULL, NULL);
03593                 if(hr == VFW_S_NOPREVIEWPIN)
03594                  {
03595                         // preview was faked up for us using the (only) capture pin
03596                         cCap->fPreviewFaked = TRUE;
03597                  }
03598                 else if(hr != S_OK)
03599                  {
03600                         // maybe it's DV?
03601                         hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW,
03602                                                                                          &MEDIATYPE_Video, cCap->pVCap, NULL, NULL);
03603                         if(hr == VFW_S_NOPREVIEWPIN)
03604                          {
03605                                 // preview was faked up for us using the (only) capture pin
03606                                 cCap->fPreviewFaked = TRUE;
03607                          }
03608                         else if(hr != S_OK)
03609                          {
03610                                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("This graph cannot preview!"));
03611                                 cCap->fPreviewGraphBuilt = FALSE;
03612                                 return false;
03613                          }
03614                  }
03615 
03616                 //
03617                 // Render the closed captioning pin? It could be a CC or a VBI category pin,
03618                 // depending on the capture driver
03619                 //
03620 
03621                 if(cCap->fCapCC)
03622                  {
03623                         hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_CC, NULL,
03624                                                                                          cCap->pVCap, NULL, NULL);
03625                         if(hr != NOERROR)
03626                          {
03627                                 hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_VBI, NULL,
03628                                                                                                  cCap->pVCap, NULL, NULL);
03629                                 if(hr != NOERROR)
03630                                  {
03631                                         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Cannot render closed captioning"));
03632                                  }
03633                          }
03634                  }
03635 
03636                 //
03637                 // add sample grabber if requested
03638                 //
03639                 if ( cCap->GrabbingEnabled )
03640                         BuildGrabberGraph(false);
03641 
03642           }
03643 
03644 
03645 
03646     //
03647     // Get the preview window to be a child of our app's window
03648     //
03649 
03650     // This will find the IVideoWindow interface on the renderer.  It is
03651     // important to ask the filtergraph for this interface... do NOT use
03652     // ICaptureGraphBuilder2::FindInterface, because the filtergraph needs to
03653     // know we own the window so it can give us display changed messages, etc.
03654 
03655     hr = cCap->pFg->QueryInterface(IID_IVideoWindow, (void **)&cCap->pVW);
03656     if(hr != NOERROR)
03657     {
03658         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("This graph cannot preview properly"));
03659     }
03660     else
03661     {
03662         //Find out if this is a DV stream
03663         AM_MEDIA_TYPE * pmtDV;
03664 
03665         if(cCap->pVSC && SUCCEEDED(cCap->pVSC->GetFormat(&pmtDV)))
03666         {
03667             if(pmtDV->formattype == FORMAT_DvInfo)
03668             {
03669                 // in this case we want to set the size of the parent window to that of
03670                 // current DV resolution.
03671                 // We get that resolution from the IVideoWindow.
03672                 CComQIPtr <IBasicVideo, &IID_IBasicVideo> pBV(cCap->pVW);
03673 
03674                 if(pBV != NULL)
03675                 {
03676                     HRESULT hr1, hr2;
03677                     long lWidth, lHeight;
03678 
03679                     hr1 = pBV->get_VideoHeight(&lHeight);
03680                     hr2 = pBV->get_VideoWidth(&lWidth);
03681                     if(SUCCEEDED(hr1) && SUCCEEDED(hr2))
03682                     {
03683                                                 width = (unsigned int)lWidth;
03684                                                 height = (unsigned int)lHeight;
03685 
03686                                                 // resize our window to the default capture size
03687                                                 if ( cCap->autoUpdateWindow )
03688                                                         ResizeWindow(cCap->ghwndApp, width, height);
03689 
03690                     }
03691                 }
03692             }
03693         }
03694 
03695         RECT rc;
03696         cCap->pVW->put_Owner((OAHWND)cCap->ghwndApp);    // We own the window now
03697         cCap->pVW->put_WindowStyle(WS_CHILD);    // you are now a child
03698 
03699         // give the preview window all our space but where the status bar is
03700         GetClientRect(cCap->ghwndApp, &rc);
03701 //        cyBorder = GetSystemMetrics(SM_CYBORDER);
03702 //        cy = statusGetHeight() + cyBorder;
03703 //        rc.bottom -= cy;
03704 
03705         cCap->pVW->SetWindowPosition(0, 0, rc.right, rc.bottom); // be this big
03706         cCap->pVW->put_Visible(OATRUE);
03707     }
03708 
03709     // now tell it what frame rate to capture at.  Just find the format it
03710     // is capturing with, and leave everything alone but change the frame rate
03711     // No big deal if it fails.  It's just for preview
03712     // !!! Should we then talk to the preview pin?
03713     if(cCap->pVSC && cCap->fUseFrameRate)
03714     {
03715         hr = cCap->pVSC->GetFormat(&pmt);
03716 
03717         // DV capture does not use a VIDEOINFOHEADER
03718         if(hr == NOERROR)
03719         {
03720             if(pmt->formattype == FORMAT_VideoInfo)
03721             {
03722                 VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *)pmt->pbFormat;
03723                 pvi->AvgTimePerFrame = (LONGLONG)(10000000 / cCap->FrameRate);
03724 
03725                 hr = cCap->pVSC->SetFormat(pmt);
03726                 if(hr != NOERROR)
03727                     ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("%x: Cannot set frame rate for preview"), hr);
03728             }
03729             DeleteMediaType(pmt);
03730         }
03731     }
03732 
03733     // make sure we process events while we're previewing!
03734     hr = cCap->pFg->QueryInterface(IID_IMediaEventEx, (void **)&cCap->pME);
03735     if(hr == NOERROR)
03736     {
03737         cCap->pME->SetNotifyWindow((OAHWND)cCap->ghwndApp, WM_FGNOTIFY, 0);
03738     }
03739 
03740     // potential debug output - what the graph looks like
03741     // DumpGraph(cCap->pFg, 1);
03742 
03743     // Add our graph to the running object table, which will allow
03744     // the GraphEdit application to "spy" on our graph
03745 #ifdef REGISTER_FILTERGRAPH
03746     hr = AddGraphToRot(cCap->pFg, &g_dwGraphRegister);
03747     if(FAILED(hr))
03748     {
03749         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Failed to register filter graph with ROT!  hr=0x%x"), hr);
03750         g_dwGraphRegister = 0;
03751     }
03752 #endif
03753 
03754     // All done.
03755     cCap->fPreviewGraphBuilt = TRUE;
03756     return VETRET_OK;
03757 }
03758 
03761 
03762 // Start previewing
03763 //
03764 int vetDirectXInput2::StartPreview()
03765  {
03766     // way ahead of you
03767     if(cCap->fPreviewing)
03768         return VETRET_ILLEGAL_USE;
03769 
03770     if(!cCap->fPreviewGraphBuilt)
03771         {
03772                 BuildPreviewGraph();
03773 
03774                 if(!cCap->fPreviewGraphBuilt)
03775                 return VETRET_INTERNAL_ERR;
03776         }
03777 
03778     // run the graph
03779     IMediaControl *pMC = NULL;
03780     HRESULT hr = cCap->pFg->QueryInterface(IID_IMediaControl, (void **)&pMC);
03781     if(SUCCEEDED(hr))
03782     {
03783         hr = pMC->Run();
03784         if(FAILED(hr))
03785         {
03786             // stop parts that ran
03787             pMC->Stop();
03788         }
03789         pMC->Release();
03790     }
03791     if(FAILED(hr))
03792     {
03793         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error %x: Cannot run preview graph"), hr);
03794         return VETRET_INTERNAL_ERR;
03795     }
03796 
03797     cCap->fPreviewing = TRUE;
03798     return VETRET_OK;
03799  }
03800 
03802 
03803 // stop the preview graph
03804 //
03805 int vetDirectXInput2::StopPreview()
03806 {
03807     // way ahead of you
03808     if(!cCap->fPreviewing)
03809         return VETRET_ILLEGAL_USE;
03810 
03811     // stop the graph
03812     IMediaControl *pMC = NULL;
03813     HRESULT hr = cCap->pFg->QueryInterface(IID_IMediaControl, (void **)&pMC);
03814     if(SUCCEEDED(hr))
03815     {
03816         hr = pMC->Stop();
03817         pMC->Release();
03818     }
03819     if(FAILED(hr))
03820     {
03821         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error %x: Cannot stop preview graph"), hr);
03822         return VETRET_INTERNAL_ERR;
03823     }
03824 
03825     cCap->fPreviewing = FALSE;
03826 
03827     // get rid of menu garbage
03828     InvalidateRect(cCap->ghwndApp, NULL, TRUE);
03829 
03830     return VETRET_OK;
03831 }
03832 
03833 void vetDirectXInput2::setPreviewEnabled(bool value)
03834  {
03835         cCap->fWantPreview = value;
03836  }
03837 
03838 
03841 
03842 // start the capture graph
03843 //
03844 int vetDirectXInput2::StartCapture()
03845 {
03846     bool fHasStreamControl;
03847     HRESULT hr;
03848 
03849     // way ahead of you
03850     if(cCap->fCapturing)
03851     {
03852         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error: Already Capturing!"));
03853         return VETRET_ILLEGAL_USE;
03854     }
03855 
03856     // or we'll get confused
03857         bool didPreview = cCap->fPreviewing;
03858     if(cCap->fPreviewing)
03859         StopPreview();
03860 
03861 
03862         if(cCap->fPreviewGraphBuilt)
03863                 TearDownGraph();
03864 
03865         BuildCaptureGraph();
03866 
03867     // or we'll crash
03868     if(!cCap->fCaptureGraphBuilt)
03869     {
03870         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error: Cannot create graph, capture falied!"));
03871         return VETRET_INTERNAL_ERR;
03872     }
03873 
03874     // This amount will be subtracted from the number of dropped and not
03875     // dropped frames reported by the filter.  Since we might be having the
03876     // filter running while the pin is turned off, we don't want any of the
03877     // frame statistics from the time the pin is off interfering with the
03878     // statistics we gather while the pin is on
03879     cCap->lDroppedBase = 0;
03880     cCap->lNotBase = 0;
03881 
03882     REFERENCE_TIME start = MAX_TIME, stop = MAX_TIME;
03883 
03884     // don't capture quite yet...
03885     hr = cCap->pBuilder->ControlStream(&PIN_CATEGORY_CAPTURE, NULL,
03886                                       NULL, &start, NULL, 0, 0);
03887 
03888     // Do we have the ability to control capture and preview separately?
03889     fHasStreamControl = SUCCEEDED(hr);
03890 
03891     // prepare to run the graph
03892     IMediaControl *pMC = NULL;
03893     hr = cCap->pFg->QueryInterface(IID_IMediaControl, (void **)&pMC);
03894     if(FAILED(hr))
03895     {
03896         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error %x: Cannot get IMediaControl"), hr);
03897         return VETRET_INTERNAL_ERR;
03898     }
03899 
03900     // If we were able to keep capture off, then we can
03901     // run the graph now for frame accurate start later yet still showing a
03902     // preview.   Otherwise, we can't run the graph yet without capture
03903     // starting too, so we'll pause it so the latency between when they
03904     // press a key and when capture begins is still small (but they won't have
03905     // a preview while they wait to press a key)
03906 
03907     if(fHasStreamControl)
03908         hr = pMC->Run();
03909     else
03910         hr = pMC->Pause();
03911     if(FAILED(hr))
03912     {
03913         // stop parts that started
03914         pMC->Stop();
03915         pMC->Release();
03916         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error %x: Cannot start graph"), hr);
03917         return VETRET_INTERNAL_ERR;
03918     }
03919 
03920 
03921     if(fHasStreamControl)
03922     {
03923         // we may not have this yet
03924         if(!cCap->pDF)
03925         {
03926             hr = cCap->pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
03927                                               &MEDIATYPE_Interleaved, cCap->pVCap,
03928                                               IID_IAMDroppedFrames, (void **)&cCap->pDF);
03929             if(hr != NOERROR)
03930                 hr = cCap->pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
03931                                                   &MEDIATYPE_Video, cCap->pVCap,
03932                                                   IID_IAMDroppedFrames, (void **)&cCap->pDF);
03933         }
03934 
03935         // turn the capture pin on now!
03936         hr = cCap->pBuilder->ControlStream(&PIN_CATEGORY_CAPTURE, NULL,
03937             NULL, NULL, &stop, 0, 0);
03938         // make note of the current dropped frame counts
03939 
03940         if(cCap->pDF)
03941         {
03942             cCap->pDF->GetNumDropped(&cCap->lDroppedBase);
03943             cCap->pDF->GetNumNotDropped(&cCap->lNotBase);
03944         }
03945     }
03946     else
03947     {
03948         hr = pMC->Run();
03949         if(FAILED(hr))
03950         {
03951             // stop parts that started
03952             pMC->Stop();
03953             pMC->Release();
03954             ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error %x: Cannot run graph"), hr);
03955             return VETRET_INTERNAL_ERR;
03956         }
03957     }
03958 
03959     pMC->Release();
03960 
03961     // when did we start capture?
03962     cCap->lCapStartTime = timeGetTime();
03963         cCap->lCapStopTime = 0;
03964 
03965     // update status bar 30 times per second - #captured, #dropped
03966 //    SetTimer(cCap->ghwndApp, 1, 33, NULL);
03967     UpdateStatus(true);
03968 
03969     cCap->fCapturing = TRUE;
03970 
03971     return VETRET_OK;
03972 }
03973 
03975 
03976 // stop the capture graph
03977 //
03978 int vetDirectXInput2::StopCapture()
03979 {
03980     // way ahead of you
03981     if(!cCap->fCapturing)
03982     {
03983         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error: Start Capturing first!"));
03984         return VETRET_INTERNAL_ERR;
03985     }
03986 
03987     // stop the graph
03988     IMediaControl *pMC = NULL;
03989     HRESULT hr = cCap->pFg->QueryInterface(IID_IMediaControl, (void **)&pMC);
03990     if(SUCCEEDED(hr))
03991     {
03992         hr = pMC->Stop();
03993         pMC->Release();
03994     }
03995     if(FAILED(hr))
03996     {
03997         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error %x: Cannot stop graph"), hr);
03998         return VETRET_INTERNAL_ERR;
03999     }
04000 
04001     // when the graph was stopped
04002     cCap->lCapStopTime = timeGetTime();
04003 
04004     // no more status bar updates
04005 //    KillTimer(cCap->ghwndApp, 1);
04006 
04007     // one last time for the final count and all the stats
04008     UpdateStatus(true);
04009 
04010     cCap->fCapturing = FALSE;
04011 
04012     // get rid of menu garbage
04013 //    InvalidateRect(cCap->ghwndApp, NULL, TRUE);
04014 
04015         if (cCap->fPreviewing && cCap->fWantPreview)
04016         {
04017                 BuildPreviewGraph();
04018                 StartPreview();
04019         }
04020 
04021 
04022     return VETRET_OK;
04023 }
04024 
04027 
04028 
04029 
04030 
04031 void vetDirectXInput2::enumerateDevices()
04032 {
04033         cCap->iNumVCapDevices = 0;
04034 
04035     UINT    uIndex = 0;
04036     HRESULT hr;
04037 
04038     // enumerate all video capture devices
04039     ICreateDevEnum *pCreateDevEnum=0;
04040     hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
04041                           IID_ICreateDevEnum, (void**)&pCreateDevEnum);
04042     if(hr != NOERROR)
04043     {
04044         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Error Creating Device Enumerator"));
04045         return;
04046     }
04047 
04048     IEnumMoniker *pEm=0;
04049     hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0);
04050     if(hr != NOERROR)
04051     {
04052         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Sorry, you have no video capture hardware.\r\n\r\n")
04053                TEXT("Video capture will not function properly."));
04054         goto EnumAudio;
04055     }
04056 
04057     pEm->Reset();
04058     ULONG cFetched;
04059     IMoniker *pM;
04060 
04061     while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
04062     {
04063 
04064         IPropertyBag *pBag=0;
04065 
04066         hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
04067         if(SUCCEEDED(hr))
04068         {
04069             VARIANT var;
04070             var.vt = VT_BSTR;
04071             hr = pBag->Read(L"FriendlyName", &var, NULL);
04072             if(hr == NOERROR)
04073             {
04074 
04075 
04076       char* str = Wide2Char(var.bstrVal);
04077       sprintf(deviceVideoDesc[uIndex], "%d - %s", uIndex, str);
04078       free(str);
04079 
04080 
04081                 SysFreeString(var.bstrVal);
04082 
04083                 ASSERT(cCap->rgpmVideoMenu[uIndex] == 0);
04084                 cCap->rgpmVideoMenu[uIndex] = pM;
04085                 pM->AddRef();
04086             }
04087             pBag->Release();
04088         }
04089 
04090         pM->Release();
04091         uIndex++;
04092     }
04093     pEm->Release();
04094 
04095     cCap->iNumVCapDevices = uIndex;
04096 
04097 
04098 
04099 EnumAudio:
04100 
04101     // enumerate all audio capture devices
04102     uIndex = 0;
04103 
04104     ASSERT(pCreateDevEnum != NULL);
04105 
04106     hr = pCreateDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEm, 0);
04107     pCreateDevEnum->Release();
04108     if(hr != NOERROR)
04109         return;
04110     pEm->Reset();
04111 
04112     while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
04113     {
04114 
04115         IPropertyBag *pBag;
04116         hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
04117         if(SUCCEEDED(hr))
04118         {
04119             VARIANT var;
04120             var.vt = VT_BSTR;
04121             hr = pBag->Read(L"FriendlyName", &var, NULL);
04122             if(hr == NOERROR)
04123             {
04124 
04125       char* str = Wide2Char(var.bstrVal);
04126       sprintf(deviceAudioDesc[uIndex], "%d - %s", uIndex, str);
04127       free(str);
04128 
04129                 SysFreeString(var.bstrVal);
04130 
04131                 ASSERT(cCap->rgpmAudioMenu[uIndex] == 0);
04132                 cCap->rgpmAudioMenu[uIndex] = pM;
04133                 pM->AddRef();
04134             }
04135             pBag->Release();
04136         }
04137         pM->Release();
04138         uIndex++;
04139     }
04140 
04141     pEm->Release();
04142 
04143     cCap->iNumACapDevices = uIndex;
04144 
04145 }
04146 
04148 
04149 
04150 void vetDirectXInput2::RegisterDevicesNotification()
04151 {
04152     // Register for device add/remove notifications
04153     DEV_BROADCAST_DEVICEINTERFACE filterData;
04154     ZeroMemory(&filterData, sizeof(DEV_BROADCAST_DEVICEINTERFACE));
04155 
04156     filterData.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
04157     filterData.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
04158     filterData.dbcc_classguid = AM_KSCATEGORY_CAPTURE;
04159 
04160     gpUnregisterDeviceNotification = NULL;
04161     gpRegisterDeviceNotification = NULL;
04162     // dynload device removal APIs
04163     {
04164         HMODULE hmodUser = GetModuleHandle(TEXT("user32.dll"));
04165         ASSERT(hmodUser);       // we link to user32
04166         gpUnregisterDeviceNotification = (PUnregisterDeviceNotification)
04167         GetProcAddress(hmodUser, "UnregisterDeviceNotification");
04168 
04169         // m_pRegisterDeviceNotification is prototyped differently in unicode
04170         gpRegisterDeviceNotification = (PRegisterDeviceNotification)
04171             GetProcAddress(hmodUser,
04172 #ifdef UNICODE
04173             "RegisterDeviceNotificationW"
04174 #else
04175             "RegisterDeviceNotificationA"
04176 #endif
04177         );
04178 
04179         // failures expected on older platforms.
04180         ASSERT(gpRegisterDeviceNotification && gpUnregisterDeviceNotification ||
04181               !gpRegisterDeviceNotification && !gpUnregisterDeviceNotification);
04182     }
04183 
04184     ghDevNotify = NULL;
04185 
04186     if(gpRegisterDeviceNotification)
04187     {
04188         ghDevNotify = gpRegisterDeviceNotification(cCap->ghwndApp, &filterData, DEVICE_NOTIFY_WINDOW_HANDLE);
04189         ASSERT(ghDevNotify != NULL);
04190     }
04191 
04192 
04193 }
04194 
04195 
04196 
04198 
04199 int vetDirectXInput2::showCaptureVideoForWindowPropertyPage()
04200  {
04201         // they want the VfW format dialog
04202         if (!cCap->pDlg)
04203          {
04204                  return VETRET_ILLEGAL_USE;
04205          }
04206 
04207         // this dialog will not work while previewing
04208         bool didPreview = false;
04209 
04210         if(cCap->fPreviewing)
04211          {
04212                 StopPreview();
04213                 didPreview = true;
04214          }
04215 
04216         HRESULT hrD;
04217         hrD = cCap->pDlg->ShowDialog(VfwCaptureDialog_Format, cCap->ghwndApp);
04218 
04219         // Sometimes bringing up the FORMAT dialog can result
04220         // in changing to a capture format that the current graph
04221         // can't handle.  It looks like that has happened and we'll
04222         // have to rebuild the graph.
04223         if(hrD == VFW_E_CANNOT_CONNECT)
04224         {
04225                 DbgLog((LOG_TRACE,1,TEXT("DIALOG CORRUPTED GRAPH!")));
04226                 TearDownGraph();    // now we need to rebuild
04227                 // !!! This won't work if we've left a stranded h/w codec
04228                 return VETRET_INTERNAL_ERR;
04229         }
04230 
04231         // Resize our window to be the same size that we're capturing
04232         if(cCap->pVSC)
04233         {
04234                 AM_MEDIA_TYPE *pmt;
04235                 // get format being used NOW
04236                 hrD = cCap->pVSC->GetFormat(&pmt);
04237 
04238                 // DV capture does not use a VIDEOINFOHEADER
04239                 if(hrD == NOERROR)
04240                 {
04241                         if(pmt->formattype == FORMAT_VideoInfo)
04242                         {
04243                                 width = HEADER(pmt->pbFormat)->biWidth;
04244                                 height = abs(HEADER(pmt->pbFormat)->biHeight);
04245 
04246                                 // resize our window to the default capture size
04247                                 if ( cCap->autoUpdateWindow )
04248                                         ResizeWindow(cCap->ghwndApp, width, height);
04249                         }
04250                         DeleteMediaType(pmt);
04251                 }
04252                 else
04253                 {
04254                         return VETRET_INTERNAL_ERR;
04255                 }
04256         }
04257 
04258         if(didPreview)
04259         {
04260                 BuildPreviewGraph();
04261                 StartPreview();
04262         }
04263         return VETRET_OK;
04264  }
04265 
04266 
04267 HRESULT showFilterPropertyPage(IBaseFilter* target, HWND ghwndApp)
04268  {
04269         HRESULT hr;
04270 
04271         ISpecifyPropertyPages *pSpec;
04272         CAUUID cauuid;
04273 
04274         hr = target->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec);
04275 
04276         if(hr == S_OK)
04277          {
04278                 hr = pSpec->GetPages(&cauuid);
04279 
04280                 hr = OleCreatePropertyFrame(    ghwndApp, 30, 30, NULL, 1,
04281                                                                                 (IUnknown **)&target, cauuid.cElems,
04282                                                                                 (GUID *)cauuid.pElems, 0, 0, NULL               );
04283 
04284                 CoTaskMemFree(cauuid.pElems);
04285                 pSpec->Release();
04286 
04287          }
04288         return hr;
04289  }
04290 
04292 int vetDirectXInput2::showCaptureVideoFilterPropertyPage()
04293  {
04294         if ( !cCap->pVCap )
04295                 return VETRET_ILLEGAL_USE;
04296 
04297         HRESULT hr;
04298 
04299         hr = showFilterPropertyPage(cCap->pVCap, cCap->ghwndApp);
04300 
04301         if(hr == S_OK)
04302                 return VETRET_OK;
04303 
04304         else
04305                 return VETRET_INTERNAL_ERR;
04306  }
04308 int vetDirectXInput2::showCaptureAudioFilterPropertyPage()
04309  {
04310         if ( !cCap->pACap )
04311                 return VETRET_ILLEGAL_USE;
04312 
04313         HRESULT hr;
04314 
04315         hr = showFilterPropertyPage(cCap->pACap, cCap->ghwndApp);
04316 
04317         if(hr == S_OK)
04318                 return VETRET_OK;
04319 
04320         else
04321                 return VETRET_INTERNAL_ERR;
04322  }
04324 int vetDirectXInput2::showVideoRendererPropertyPage()
04325 {
04326         if ( !cCap->pRender )
04327                 return VETRET_ILLEGAL_USE;
04328 
04329         HRESULT hr;
04330 
04331         hr = showFilterPropertyPage(cCap->pRender, cCap->ghwndApp);
04332 
04333         if(hr == S_OK)
04334                 return VETRET_OK;
04335 
04336         else
04337                 return VETRET_INTERNAL_ERR;
04338  }
04340 int vetDirectXInput2::showSampleGrabberPropertyPage()
04341 {
04342         if ( !cCap->pGrabberBaseFilter )
04343                 return VETRET_ILLEGAL_USE;
04344 
04345         HRESULT hr;
04346 
04347         hr = showFilterPropertyPage(cCap->pGrabberBaseFilter, cCap->ghwndApp);
04348 
04349         if(hr == S_OK)
04350                 return VETRET_OK;
04351 
04352         else
04353                 return VETRET_INTERNAL_ERR;
04354  }
04356 
04357 
04358 int vetDirectXInput2::showGraphFilterPropertyPage()
04359 {
04360                 // You can change this pin's output format in these dialogs.
04361                 // If the capture pin is already connected to somebody who's
04362                 // fussy about the connection type, that may prevent using
04363                 // this dialog(!) because the filter it's connected to might not
04364                 // allow reconnecting to a new format. (EG: you switch from RGB
04365                 // to some compressed type, and need to pull in a decoder)
04366                 // I need to tear down the graph downstream of the
04367                 // capture filter before bringing up these dialogs.
04368                 // In any case, the graph must be STOPPED when calling them.
04369         HRESULT hr;
04370 //      bool didPreview = cCap->fPreviewing;
04371 
04372 //      if(cCap->fPreviewing)
04373 //              StopPreview();  // make sure graph is stopped
04374 
04375 //      if(cCap->fCapturing)
04376 //              StopCapture();  // make sure graph is stopped
04377 
04378                 // The capture pin that we are trying to set the format on is connected if
04379                 // one of these variable is set to TRUE. The pin should be disconnected for
04380                 // the dialog to work properly.
04381                 if(cCap->fCaptureGraphBuilt || cCap->fPreviewGraphBuilt)
04382                 {
04383                     DbgLog((LOG_TRACE,1,TEXT("Tear down graph for dialog")));
04384                     TearDownGraph();    // graph could prevent dialog working
04385                 }
04386 
04387                 IAMStreamConfig *pSC;
04388                 hr = cCap->pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
04389                     &MEDIATYPE_Interleaved, cCap->pVCap,
04390                     IID_IAMStreamConfig, (void **)&pSC);
04391 
04392                 if(hr != NOERROR)
04393                     hr = cCap->pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
04394                         &MEDIATYPE_Video, cCap->pVCap,
04395                         IID_IAMStreamConfig, (void **)&pSC);
04396 
04397                 ISpecifyPropertyPages *pSpec;
04398                 CAUUID cauuid;
04399 
04400                 hr = pSC->QueryInterface(IID_ISpecifyPropertyPages,
04401                     (void **)&pSpec);
04402 
04403                 if(hr == S_OK)
04404                 {
04405                     hr = pSpec->GetPages(&cauuid);
04406                     hr = OleCreatePropertyFrame(cCap->ghwndApp, 30, 30, NULL, 1,
04407                         (IUnknown **)&pSC, cauuid.cElems,
04408                         (GUID *)cauuid.pElems, 0, 0, NULL);
04409 
04410                     // !!! What if changing output formats couldn't reconnect
04411                     // and the graph is broken?  Shouldn't be possible...
04412 
04413                     if(cCap->pVSC)
04414                     {
04415                         AM_MEDIA_TYPE *pmt;
04416                         // get format being used NOW
04417                         hr = cCap->pVSC->GetFormat(&pmt);
04418 
04419                         // DV capture does not use a VIDEOINFOHEADER
04420                         if(hr == NOERROR)
04421                         {
04422                             if(pmt->formattype == FORMAT_VideoInfo)
04423                             {
04424                                                                 width = HEADER(pmt->pbFormat)->biWidth;
04425                                                                 height = abs(HEADER(pmt->pbFormat)->biHeight);
04426 
04427                                                                 // resize our window to the default capture size
04428                                                                 if ( cCap->autoUpdateWindow )
04429                                                                         ResizeWindow(cCap->ghwndApp, width, height);
04430 
04431                             }
04432                             DeleteMediaType(pmt);
04433                         }
04434                     }
04435 
04436                     CoTaskMemFree(cauuid.pElems);
04437                     pSpec->Release();
04438                 }
04439 
04440                 pSC->Release();
04441 
04442 //              if(didPreview)
04443 //                    StartPreview();
04444 
04445         return 0;
04446 }
04447 
04448 
04449 
04451 
04452 
04453 // pre-allocate the capture file
04454 //
04455 int vetDirectXInput2::AllocCaptureFile(unsigned short fileSize_mb)
04456  {
04457         USES_CONVERSION;
04458 
04459         // we'll get into an infinite loop in the dlg proc setting a value
04460         if( cCap->szCaptureFile[0] == 0 )
04461          {
04462                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Allocation falied:\r\nCapture file is not valid!\r\n\r\nDid you setup it?"));
04463                 return VETRET_ILLEGAL_USE;
04464          }
04465 
04466         cCap->wCapFileSize = (WORD)fileSize_mb;
04467 
04468         // ensure repaint after dismissing dialog before
04469         // possibly lengthy operation
04470         //UpdateWindow(cCap->ghwndApp);
04471 
04472         if( MakeBuilder() )
04473          {
04474                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Allocation falied:\r\nCannot create graph Builder!"));
04475                 return VETRET_INTERNAL_ERR;
04476          }
04477 
04478         if( cCap->pBuilder->AllocCapFile(T2W(cCap->szCaptureFile), (DWORDLONG)cCap->wCapFileSize * 1024L * 1024L) != NOERROR )
04479          {
04480                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Allocation falied:\r\nFailed to pre-allocate capture file space!"));
04481                 return VETRET_INTERNAL_ERR;
04482          }
04483 
04484         return VETRET_OK;
04485  }
04486 
04487 
04489 
04490 /*
04491  * Put up a dialog to allow the user to select a capture file.
04492  */
04493 int vetDirectXInput2::setCaptureFile(char* pszName)
04494 {
04495         lstrcpyn(cCap->szCaptureFile, pszName, _MAX_PATH);
04496 
04497         USES_CONVERSION;
04498 
04499         OFSTRUCT os;
04500 
04501         // We have a capture file name
04502 
04503         // If this is a new file, then invite the user to allocate some space
04504 #ifdef UNICODE
04505         // Convert Multibyte string to ANSI
04506         char szCaptureFile[STR_MAX_LENGTH];
04507         int rc = WideCharToMultiByte(CP_ACP, 0, cCap->szCaptureFile, -1,
04508                                      szCaptureFile, STR_MAX_LENGTH, NULL, NULL);
04509 #else
04510         TCHAR *szCaptureFile = cCap->szCaptureFile;
04511 #endif
04512 
04513         if(OpenFile(szCaptureFile, &os, OF_EXIST) == HFILE_ERROR)
04514         {
04515             // bring up dialog, and set new file size
04516             if( AllocCaptureFile() )
04517                 return VETRET_INTERNAL_ERR;
04518         }
04519 
04520     // tell the file writer to use the new filename
04521     if(cCap->pSink)
04522     {
04523         cCap->pSink->SetFileName(T2W(cCap->szCaptureFile), NULL);
04524     }
04525 
04526     return VETRET_OK;
04527 }
04528 
04529 
04531 
04532 double vetDirectXInput2::getFrameRateCurrent()
04533  {
04534     HRESULT hr = E_FAIL;
04535         double ret = 0.0;
04536         if(cCap->pVSC)
04537         {
04538                 AM_MEDIA_TYPE *pmt;
04539                 hr = cCap->pVSC->GetFormat(&pmt);
04540 
04541                 // DV capture does not use a VIDEOINFOHEADER
04542                 if(hr == NOERROR)
04543                 {
04544                         if(pmt->formattype == FORMAT_VideoInfo)
04545                         {
04546                                 VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *)pmt->pbFormat;
04547                                 ret = (double)(10000000 / pvi->AvgTimePerFrame);
04548 
04549                         }
04550                         DeleteMediaType(pmt);
04551                 }
04552         }
04553         return ret;
04554  }
04555 
04556 
04557 // Allow the user to choose a frame rate
04558 //
04559 int vetDirectXInput2::setFrameRate(double rate)
04560 {
04561     if ( rate <= 0.0 )
04562                 return VETRET_PARAM_ERR;
04563 
04564         if (!cCap->fUseFrameRate)
04565                 return VETRET_ILLEGAL_USE;
04566 
04567         if (rate == cCap->FrameRate)
04568                 return VETRET_OK;
04569 
04570     HRESULT hr = E_FAIL;
04571 
04572     // If somebody unchecks "use frame rate" it means we will no longer
04573     // tell the filter what frame rate to use... it will either continue
04574     // using the last one, or use some default, or if you bring up a dialog
04575     // box that has frame rate choices, it will obey them.
04576 
04577         bool didPrev = cCap->fPreviewing;
04578         if(cCap->fPreviewing)
04579                 StopPreview();
04580 
04581         // now tell it what frame rate to capture at.  Just find the format it
04582         // is capturing with, and leave everything else alone
04583         if(cCap->pVSC)
04584         {
04585                 AM_MEDIA_TYPE *pmt;
04586                 hr = cCap->pVSC->GetFormat(&pmt);
04587 
04588                 // DV capture does not use a VIDEOINFOHEADER
04589                 if(hr == NOERROR)
04590                 {
04591                         if(pmt->formattype == FORMAT_VideoInfo)
04592                         {
04593                                 VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *)pmt->pbFormat;
04594                                 pvi->AvgTimePerFrame =(LONGLONG)(10000000 / cCap->FrameRate);
04595 
04596                                 hr = cCap->pVSC->SetFormat(pmt);
04597                                 if(hr != S_OK)
04598                                 {
04599                                         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("%x: Cannot set new frame rate"), hr);
04600                                         return VETRET_INTERNAL_ERR;
04601                                 }
04602                         }
04603                         DeleteMediaType(pmt);
04604                 }
04605         }
04606 
04607         if(hr != NOERROR)
04608         {
04609                 ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Cannot set frame rate for capture"));
04610                 return VETRET_INTERNAL_ERR;
04611         }
04612         if(didPrev)  // we were previewing
04613                 StartPreview();
04614 
04615         return VETRET_OK;
04616 }
04617 
04618 
04619 /* error in include file? msacm.h
04620 
04621 
04622 // choose an audio capture format using ACM
04623 //
04624 void vetDirectXInput2::ChooseAudioFormat()
04625 {
04626     ACMFORMATCHOOSE cfmt;
04627     DWORD dwSize;
04628     LPWAVEFORMATEX lpwfx;
04629     AM_MEDIA_TYPE *pmt;
04630 
04631     // there's no point if we can't set a new format
04632     if(cCap->pASC == NULL)
04633         return;
04634 
04635     // What's the largest format size around?
04636     acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, &dwSize);
04637     HRESULT hr = cCap->pASC->GetFormat(&pmt);
04638     if(hr != NOERROR)
04639         return;
04640 
04641     lpwfx = (LPWAVEFORMATEX)pmt->pbFormat;
04642     dwSize = (DWORD) (max(dwSize, lpwfx->cbSize + sizeof(WAVEFORMATEX)));
04643 
04644     // !!! This doesn't really map to the supported formats of the filter.
04645     // We should be using a property page based on IAMStreamConfig
04646 
04647     // Put up a dialog box initialized with the current format
04648     lpwfx = (LPWAVEFORMATEX)GlobalAllocPtr(GHND, dwSize);
04649     if(lpwfx)
04650     {
04651         CopyMemory(lpwfx, pmt->pbFormat, pmt->cbFormat);
04652         _fmemset(&cfmt, 0, sizeof(ACMFORMATCHOOSE));
04653         cfmt.cbStruct = sizeof(ACMFORMATCHOOSE);
04654         cfmt.fdwStyle = ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT;
04655 
04656         // show only formats we can capture
04657         cfmt.fdwEnum = ACM_FORMATENUMF_HARDWARE | ACM_FORMATENUMF_INPUT;
04658         cfmt.hwndOwner = cCap->ghwndApp;
04659         cfmt.pwfx = lpwfx;
04660         cfmt.cbwfx = dwSize;
04661 
04662         // we chose a new format... so give it to the capture filter
04663         if(!acmFormatChoose(&cfmt))
04664         {
04665             if(cCap->fPreviewing)
04666                 StopPreview();  // can't call IAMStreamConfig::SetFormat
04667 
04668             // while streaming
04669             ((CMediaType *)pmt)->SetFormat((LPBYTE)lpwfx,
04670                 lpwfx->cbSize + sizeof(WAVEFORMATEX));
04671 
04672             cCap->pASC->SetFormat(pmt);  // filter will reconnect
04673             if(cCap->fWantPreview)
04674                 StartPreview();
04675         }
04676         GlobalFreePtr(lpwfx) ;
04677     }
04678 
04679     DeleteMediaType(pmt);
04680 }
04681 */
04682 
04683 
04684 
04685 
04686 
04687 
04688 
04689 
04690 
04693 
04694 
04695 // how many captured/dropped so far
04696 //
04697 void vetDirectXInput2::UpdateStatus(bool fAllStats)
04698 {
04699     HRESULT hr;
04700 //    TCHAR tach[160];
04701 
04702     // we use this interface to get the number of captured and dropped frames
04703     // NOTE:  We cannot query for this interface earlier, as it may not be
04704     // available until the pin is connected
04705     if(!cCap->pDF)
04706     {
04707         hr = cCap->pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
04708                                           &MEDIATYPE_Interleaved, cCap->pVCap,
04709                                           IID_IAMDroppedFrames, (void **)&cCap->pDF);
04710         if(hr != S_OK)
04711             hr = cCap->pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
04712                                               &MEDIATYPE_Video, cCap->pVCap,
04713                                               IID_IAMDroppedFrames, (void **)&cCap->pDF);
04714     }
04715 
04716     // this filter can't tell us dropped frame info.
04717     if(!cCap->pDF)
04718     {
04719         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Filter cannot report capture information"), hr);
04720         return;
04721     }
04722 
04723     hr = cCap->pDF->GetNumDropped(&cCap->lDroppedCurrent);
04724     if(hr == S_OK)
04725         hr = cCap->pDF->GetNumNotDropped(&cCap->lNotCurrent);
04726     if(hr != S_OK)
04727         return;
04728 
04729     cCap->lDroppedCurrent -= cCap->lDroppedBase;
04730     cCap->lNotCurrent -= cCap->lNotBase;
04731 
04732 
04733 
04734     if(!fAllStats)
04735     {
04736 //        LONG lTime = timeGetTime() - cCap->lCapStartTime;
04737 //        wsprintf(tach, TEXT("Captured %d frames (%d dropped) %d.%dsec\0"), cCap->lNotCurrent,
04738 //                 cCap->lDroppedCurrent, lTime / 1000,
04739 //                 lTime / 100 - lTime / 1000 * 10);
04740 //        statusUpdateStatus(ghwndStatus, tach);
04741         return;
04742     }
04743 
04744     // we want all possible stats, including capture time and actual acheived
04745     // frame rate and data rate (as opposed to what we tried to get).  These
04746     // numbers are an indication that though we dropped frames just now, if we
04747     // chose a data rate and frame rate equal to the numbers I'm about to
04748     // print, we probably wouldn't drop any frames.
04749 
04750     // average size of frame captured
04751     hr = cCap->pDF->GetAverageFrameSize(&cCap->lAvgFrameSizeCurrent);
04752     if(hr != S_OK)
04753         return;
04754 
04755         // how long capture lasted
04756         LONG lDurMS;
04757         if (cCap->lCapStopTime)
04758         lDurMS = cCap->lCapStopTime - cCap->lCapStartTime;
04759         else
04760             lDurMS = timeGetTime() - cCap->lCapStartTime;
04761 
04762     if(lDurMS > 0)
04763     {
04764         cCap->flFrameCurrent = (double)(LONGLONG)cCap->lNotCurrent * 1000. /
04765             (double)(LONGLONG)lDurMS;
04766         cCap->lDataCurrent = (long)(LONGLONG)(cCap->lNotCurrent / (double)(LONGLONG)lDurMS *
04767             1000. * (double)(LONGLONG)cCap->lAvgFrameSizeCurrent);
04768     }
04769     else
04770     {
04771         cCap->flFrameCurrent = 0.;
04772         cCap->lDataCurrent = 0;
04773     }
04774 /*
04775     wsprintf(tach, TEXT("Captured %d frames in %d.%d sec (%d dropped): %d.%d fps %d.%d Meg/sec\0"),
04776              cCap->lNotCurrent, lDurMS / 1000, lDurMS / 100 - lDurMS / 1000 * 10,
04777              cCap->lDroppedCurrent, (int)cCap->flFrameCurrent,
04778              (int)(cCap->flFrameCurrent * 10.) - (int)cCap->flFrameCurrent * 10,
04779              cCap->lDataCurrent / 1000000,
04780              cCap->lDataCurrent / 1000 - (cCap->lDataCurrent / 1000000 * 1000));
04781 */
04782 //    statusUpdateStatus(ghwndStatus, tach);
04783 
04784         cCap->wCapFileSize = (WORD)GetSize( cCap->szCaptureFile );
04785 
04786 }
04787 
04788 
04789 
04791 
04792 
04793 int vetDirectXInput2::setCurrentDevices(int szVideo, int szAudio)
04794  {
04795         IMoniker *pmVideo;
04796         IMoniker *pmAudio;
04797 
04798 //TODO UPPER LIMIT
04799 
04800         if (szAudio < 0)
04801          {
04802         IMonRelease(cCap->pmAudio);
04803         cCap->pmAudio = NULL;
04804 
04805         pmAudio = NULL;
04806         cCap->pmAudioIndex = -1;
04807 
04808          }
04809         else
04810                 pmAudio = cCap->rgpmAudioMenu[szAudio];
04811 
04812         if (szVideo < 0)
04813          {
04814         IMonRelease(cCap->pmVideo);
04815         cCap->pmVideo = NULL;
04816 
04817         pmVideo = NULL;
04818         cCap->pmVideoIndex = -1;
04819          }
04820         else
04821                 pmVideo = cCap->rgpmVideoMenu[szVideo];
04822 
04823         #define VERSIZE 40
04824         #define DESCSIZE 80
04825 
04826         USES_CONVERSION;
04827         int versize = VERSIZE;
04828         int descsize = DESCSIZE;
04829         WCHAR wachVer[VERSIZE]={0}, wachDesc[DESCSIZE]={0};
04830         TCHAR tachStatus[VERSIZE + DESCSIZE + 5]={0};
04831 
04832                 // they chose a new device. rebuild the graphs
04833         if(cCap->pmVideo != pmVideo || cCap->pmAudio != pmAudio)
04834          {
04835                 if(pmVideo)
04836                         pmVideo->AddRef();
04837 
04838                 if(pmAudio)
04839                         pmAudio->AddRef();
04840 
04841                 IMonRelease(cCap->pmVideo);
04842                 IMonRelease(cCap->pmAudio);
04843                 cCap->pmVideo = pmVideo;
04844                 cCap->pmAudio = pmAudio;
04845                 cCap->pmAudioIndex = szAudio;
04846         cCap->pmVideoIndex = szVideo;
04847 
04848                 if(cCap->fPreviewing)
04849                         StopPreview();
04850 
04851                 if(cCap->fCaptureGraphBuilt || cCap->fPreviewGraphBuilt)
04852                         TearDownGraph();
04853 
04854                 FreeCapFilters();
04855 
04856                 if ( InitCapFilters() )
04857                  {
04858                         FreeCapFilters();
04859                         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Cannot use selected device.\r\nGraph initialization falied."));
04860                         return VETRET_INTERNAL_ERR;
04861                  }
04862 
04863                 if(cCap->fWantPreview)   // were we previewing?
04864                  {
04865                         BuildPreviewGraph();
04866                         StartPreview();
04867                  }
04868 
04869          }
04870 
04871 
04872         // Put the video driver name - if the filter supports
04873         // IAMVideoCompression::GetInfo, that's the best way to get the name and
04874         // the version.  Otherwise use the name we got from device enumeration
04875         // as a fallback.
04876         if(cCap->pVC)
04877          {
04878                 HRESULT hr = cCap->pVC->GetInfo(wachVer, &versize, wachDesc, &descsize,
04879                                                            NULL, NULL, NULL, NULL);
04880                 if(hr == S_OK)
04881                  {
04882                         // It's possible that the call succeeded without actually filling
04883                         // in information for description and version.  If these strings
04884                         // are empty, just display the device's friendly name.
04885                         if(wcslen(wachDesc) && wcslen(wachVer))
04886                          {
04887                                 wsprintf(tachStatus, TEXT("%s - %s\0"), W2T(wachDesc), W2T(wachVer));
04888                                 ErrMsg(cCap->ghwndApp, cCap->displayErrorMessages, tachStatus);
04889                                 //                statusUpdateStatus(ghwndStatus, tachStatus);
04890                                 return VETRET_OK;
04891                          }
04892                  }
04893         }
04894         // Since the GetInfo method failed (or the interface did not exist),
04895         // display the device's friendly name.
04896         //    statusUpdateStatus(ghwndStatus, W2T(cCap->wachVideoFriendlyName));
04897 
04898         return VETRET_OK;
04899  }
04900 
04901 
04902 
04904 
04911 int vetDirectXInput2::getCurrentDeviceVideo()
04912  {
04913         return cCap->pmVideoIndex;
04914  }
04915 
04922 int vetDirectXInput2::getCurrentDeviceAudio()
04923  {
04924         return cCap->pmAudioIndex;
04925  }
04926 
04927 
04928 
04929 
04931 // frame extraction functions
04932 
04933 
04946 int vetDirectXInput2::extractTo(vetFrameYUV420& img)
04947  {
04948         INFO("int vetDirectXInput::extractTo(vetFrameCache& img) [pushing data]")
04949 
04950         return VETRET_NOT_IMPLEMENTED;
04951  }
04952 
04953 
04966 int vetDirectXInput2::extractTo(vetFrameRGB24& img)
04967  {
04968         INFO("int vetDirectXInput::extractTo(vetFrameCache24& img) [pushing data]")
04969 
04970 //      if (!cCap->GrabbingEnabled)
04971 //              return VETRET_ILLEGAL_USE;
04972         if (!cCap->pSampleGrabber)
04973                 return VETRET_INTERNAL_ERR;
04974 
04975         if (img.width != width || img.height != height)
04976                 img.reAllocCanvas(width, height);
04977 
04978         cCap->pCallbackGrabber->bufferSize = width*height*3;
04979         cCap->pCallbackGrabber->buffer = img.data[0];
04980 
04981         cCap->pCallbackGrabber->frameWanted = true;
04982 
04983         WaitForSingleObject(cCap->pCallbackGrabber->event, 100);
04984 
04985         return VETRET_OK;
04986  }
04987 
04988 
04989 
05002 int vetDirectXInput2::extractTo(vetFrameT<unsigned char>& img)
05003  {
05004         INFO("int vetDirectXInput::extractTo(vetFrameGrey& img) [pushing data]")
05005 
05006         return VETRET_NOT_IMPLEMENTED;
05007  }
05008 
05009 
05010 
05011 /*
05012 
05013 
05014 
05015 
05016 //Capture RAW IMAGE BITS 24bits/pixel
05017 DWORD vetDirectXInput2::ImageCapture(LPCTSTR szFile)
05018 {
05019         BYTE *pImage;
05020         DWORD dwSize,dwWritten;
05021         dwSize=this->GrabFrame ();
05022         this->GetFrame (&pImage);
05023 
05024         HANDLE hFile = CreateFile(szFile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
05025                                           CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
05026 
05027         if (hFile == INVALID_HANDLE_VALUE)
05028         return FALSE;
05029 
05030         WriteFile(hFile, (LPCVOID)pImage , m_nFramelen, &dwWritten, 0);
05031         // Close the file
05032         CloseHandle(hFile);
05033 
05034         return dwWritten;
05035 }
05036 
05037 
05038 DWORD vetDirectXInput2::GrabFrame()
05039 {
05040         if(m_pWC )
05041     {
05042        BYTE* lpCurrImage = NULL;
05043 
05044         // Read the current video frame into a byte buffer.  The information
05045         // will be returned in a packed Windows DIB and will be allocated
05046         // by the VMR.
05047         if(m_pWC->GetCurrentImage(&lpCurrImage) == S_OK)
05048         {
05049 
05050                         LPBITMAPINFOHEADER  pdib = (LPBITMAPINFOHEADER) lpCurrImage;
05051 
05052                         if(m_pFrame==NULL || (pdib->biHeight * pdib->biWidth * 3) !=m_nFramelen )
05053                         {
05054                                 if(m_pFrame!=NULL)
05055                                 delete []m_pFrame;
05056 
05057                                 m_nFramelen=pdib->biHeight * pdib->biWidth * 3;
05058                                 m_pFrame=new BYTE [pdib->biHeight * pdib->biWidth * 3] ;
05059 
05060 
05061                         }
05062 
05063                         if(pdib->biBitCount ==32)
05064                         {
05065                                 DWORD  dwSize=0, dwWritten=0;
05066 
05067                                 BYTE *pTemp32;
05068                                 pTemp32=lpCurrImage + sizeof(BITMAPINFOHEADER);
05069 
05070                                 //change from 32 to 24 bit /pixel
05071                                 this->Convert24Image(pTemp32, m_pFrame, pdib->biSizeImage);
05072 
05073                         }
05074 
05075                         CoTaskMemFree(lpCurrImage);     //free the image
05076                 }
05077                 else
05078                 {
05079                         return -1;
05080                 }
05081 
05082         }
05083         else
05084         {
05085                 return -1;
05086         }
05087 
05088 
05089 
05090     return m_nFramelen;
05091 
05092 }
05093 
05094 
05095 DWORD vetDirectXInput2::GetFrame(BYTE **pFrame)
05096 {
05097         if(m_pFrame && m_nFramelen)
05098         {
05099         *pFrame=m_pFrame;
05100         }
05101 
05102 
05103         return m_nFramelen;
05104 }
05105 */
05106 
05107 bool Convert24Image(BYTE *p32Img, BYTE *p24Img,DWORD dwSize32)
05108 {
05109 
05110         if(p32Img != NULL && p24Img != NULL && dwSize32>0)
05111         {
05112 
05113                 DWORD dwSize24;
05114 
05115                 dwSize24=(dwSize32 * 3)/4;
05116 
05117                 BYTE *pTemp,*ptr;
05118                 //pTemp=p32Img + sizeof(BITMAPINFOHEADER); ;
05119                 pTemp=p32Img;
05120 
05121                 ptr=p24Img + dwSize24-1 ;
05122 
05123                 int ival=0;
05124                 for (DWORD index = 0; index < dwSize32/4 ; index++)
05125                 {
05126                         unsigned char r = *(pTemp++);
05127                         unsigned char g = *(pTemp++);
05128                         unsigned char b = *(pTemp++);
05129                         (pTemp++);//skip alpha
05130 
05131                         *(ptr--) = b;
05132                         *(ptr--) = g;
05133                         *(ptr--) = r;
05134 
05135                 }
05136         }
05137         else
05138         {
05139                 return false;
05140         }
05141 
05142 return true;
05143 }
05144 
05151 
05152 
05164 //int vetDirectXInput2::getFormat(int format, int *width, int *height, char* desc)
05165 // {
05166 //  assert(vc);
05167 //  assert(vc->device != -1);
05168 //  assert(vc->format_count);
05169 /*
05170   if (format >= cCap->format_count)
05171     return VETRET_PARAM_ERR;
05172 
05173   IAMStreamConfig *pSC = vetGetStreamConfig(cCap);
05174   if (!pSC)
05175         return VETRET_INTERNAL_ERR;
05176 
05177   VIDEO_STREAM_CONFIG_CAPS scc;
05178   AM_MEDIA_TYPE *pmt;
05179   if (SUCCEEDED(pSC->GetStreamCaps(cCap->format_map[format], &pmt, (BYTE*)&scc)))
05180   {
05181     *width = scc.InputSize.cx;
05182     *height = scc.InputSize.cy;
05183     vetGetFormatName(pmt->subtype, desc);
05184 
05185     pSC->Release();
05186     vetDeleteMediaType(pmt);
05187     return VETRET_OK;
05188   }
05189 
05190   pSC->Release();
05191   return VETRET_INTERNAL_ERR;
05192  }
05193 */
05194 
05195 
05196 
05197 static void vetGetFormatName(GUID subtype, char* desc)
05198 {
05199 #define NUM_FORM 7
05200   typedef struct _guid2name {
05201     char* name;
05202     const GUID* subtype;
05203   } guid2name;
05204   static guid2name map_table[NUM_FORM] = {
05205     {"RGB1",&MEDIASUBTYPE_RGB1},
05206     {"RGB4",&MEDIASUBTYPE_RGB4},
05207     {"RGB8",&MEDIASUBTYPE_RGB8},
05208     {"RGB565",&MEDIASUBTYPE_RGB565},
05209     {"RGB555",&MEDIASUBTYPE_RGB555},
05210     {"RGB24",&MEDIASUBTYPE_RGB24},
05211     {"RGB32",&MEDIASUBTYPE_RGB32}
05212   };
05213 
05214   for (int i = 0; i < NUM_FORM; i++)
05215   {
05216     if (*(map_table[i].subtype) == subtype)
05217     {
05218       strcpy(desc, map_table[i].name);
05219       return;
05220     }
05221   }
05222 
05223   desc[0] = (char)(subtype.Data1);
05224   desc[1] = (char)(subtype.Data1 >> 8);
05225   desc[2] = (char)(subtype.Data1 >> 16);
05226   desc[3] = (char)(subtype.Data1 >> 32);
05227   desc[4] = 0;
05228 }
05229 
05230 
05231 
05234 
05235 int vetDirectXInput2::setPreviewWindow(void* HWND_Owner)
05236  {
05237         cCap->ghwndApp = static_cast<HWND>(HWND_Owner);
05238 
05239         return VETRET_OK;
05240  }
05241 
05242 double vetDirectXInput2::getFrameRate()
05243  {
05244         return cCap->FrameRate;
05245  }
05246 
05247 bool vetDirectXInput2::isPreviewing()
05248  {
05249         if ( cCap->fPreviewing )
05250                 return true;
05251         else
05252                 return false;
05253  }
05254 
05255 bool vetDirectXInput2::isCapturing()
05256  {
05257         if ( cCap->fCapturing )
05258                 return true;
05259         else
05260                 return false;
05261  }
05262 
05263 
05264 bool vetDirectXInput2::isCapturingAudio()
05265  {
05266         if ( cCap->fCapAudio )
05267                 return true;
05268         else
05269                 return false;
05270  }
05271 
05272 bool vetDirectXInput2::isUncompressed()
05273  {
05274         if ( !cCap->fMPEG2 )
05275                 return true;
05276         else
05277                 return false;
05278  }
05279 
05280 bool vetDirectXInput2::isMPEG2Encoded()
05281  {
05282         if ( cCap->fMPEG2 )
05283                 return true;
05284         else
05285                 return false;
05286  }
05287 
05288 bool vetDirectXInput2::isPreviewFaked()
05289  {
05290         if (cCap->fPreviewFaked)
05291                 return true;
05292         return false;
05293  }
05294 
05295 
05296 int vetDirectXInput2::setMPEG2Encode(bool enable)
05297  {
05298         if ( cCap->fCapturing )
05299                 return VETRET_ILLEGAL_USE;
05300 
05301         cCap->fMPEG2 = enable;
05302 
05303 
05304         return VETRET_OK;
05305  }
05306 
05307 int vetDirectXInput2::setFrameRateControlEnabled(bool enable)
05308  {
05309         cCap->fUseFrameRate = enable;
05310 
05311         return VETRET_OK;
05312  }
05313 
05314 int vetDirectXInput2::setFrameGrabbingEnabled(bool enable)
05315  {
05316         if ( cCap->fCapturing )
05317                 return VETRET_ILLEGAL_USE;
05318 
05319 //return VETRET_NOT_IMPLEMENTED;
05320 
05321         bool didPreviewing = cCap->fPreviewing;
05322 
05323         HRESULT hr = 0;
05324 
05325         if(cCap->fCaptureGraphBuilt || cCap->fPreviewGraphBuilt)
05326                 TearDownGraph();
05327 
05328         FreeCapFilters();
05329 
05330         cCap->GrabbingEnabled = enable;
05331 
05332         if (didPreviewing)   // were we previewing?
05333          {
05334                 if ( InitCapFilters() )
05335                  {
05336                         FreeCapFilters();
05337                         ErrMsg(cCap->ghwndApp,  cCap->displayErrorMessages, TEXT("Cannot enable fram grabbing.\r\nGraph initialization falied."), hr);
05338                         cCap->GrabbingEnabled = false;
05339                         InitCapFilters();
05340                         return VETRET_INTERNAL_ERR;
05341                  }
05342                 BuildPreviewGraph();
05343                 StartPreview();
05344          }
05345 
05346 
05347         return VETRET_OK;
05348  }
05349 
05350 bool vetDirectXInput2::isFrameGrabbingEnabled()
05351  {
05352          return cCap->GrabbingEnabled;
05353  }
05354 
05355 bool vetDirectXInput2::EoF()
05356 {
05357         if ( !cCap->GrabbingEnabled )
05358                 return false;
05359 
05360         if ( cCap->fCapturing || cCap->fPreviewing )
05361                 return true;
05362 
05363         return false;
05364 }
05365 
05366 
05367 int vetDirectXInput2::setCaptureAudioEnabled(bool enable)
05368  {
05369 
05370         if ( cCap->fCapturing )
05371                 return VETRET_ILLEGAL_USE;
05372 
05373         if ( cCap->fPreviewing )
05374          {
05375                 int ret = StopPreview();
05376                 //TearDownGraph();
05377                 cCap->fCapAudio = enable;
05378                 //BuildPreviewGraph();
05379                 ret += StartPreview();
05380                 if ( ret )
05381                         return VETRET_INTERNAL_ERR;
05382                 else
05383                         return VETRET_OK;
05384          }
05385 
05386         cCap->fCapAudio = enable;
05387 
05388         return VETRET_OK;
05389 
05390  }
05391 
05392 
05393 long vetDirectXInput2::getCapturedFramesCount(bool forceUpdate)
05394  {
05395         if (forceUpdate)
05396                 UpdateStatus();
05397 
05398         return cCap->lNotCurrent;
05399  }
05400 
05401 long vetDirectXInput2::getDroppedFramesCount(bool forceUpdate)
05402  {
05403         if (forceUpdate)
05404                 UpdateStatus();
05405 
05406         return cCap->lDroppedCurrent;
05407  }
05408 
05409 long vetDirectXInput2::getCapturedElapsedTime()
05410  {
05411         if ( cCap->fCapturing )
05412                 return (long)( timeGetTime() - cCap->lCapStartTime );
05413         else
05414                 return (long)( cCap->lCapStopTime - cCap->lCapStartTime );
05415 
05416  }
05417 
05418 long vetDirectXInput2::getAverageFrameSize(bool forceUpdate)
05419  {
05420         if (forceUpdate)
05421                 UpdateStatus(true);
05422 
05423         return cCap->lAvgFrameSizeCurrent;
05424  }
05425 
05426 
05427 
05428 double vetDirectXInput2::getCapturedFrameRate(bool forceUpdate)
05429  {
05430         if (forceUpdate)
05431                 UpdateStatus(true);
05432 
05433         return (long)cCap->flFrameCurrent;
05434  }
05435 
05436 
05437 long vetDirectXInput2::getCapturedDataRate(bool forceUpdate)
05438  {
05439         if (forceUpdate)
05440                 UpdateStatus(true);
05441 
05442         return cCap->lDataCurrent;
05443  }
05444 
05445 vetDirectXInput2::FORMAT_CSP vetDirectXInput2::getCurrentFormat() { return cCap->format_CSP; };
05446 
05447 int vetDirectXInput2::getCurrentFormatDescription(char* buffer)
05448  {
05449         switch (cCap->format_CSP)
05450          {
05451                  case UNKNOWN:  strcpy(buffer, "UNKNOW csp");
05452 
05453                  case VETFRAMET_CS_RGB: strcpy(buffer, "RGB24 csp");
05454 
05455          }
05456 
05457 
05458         return VETRET_OK;
05459 
05460  };
05461 
05462 
05463 
05464 unsigned short vetDirectXInput2::getFileSize(bool forceUpdate)
05465  {
05466         if (forceUpdate)
05467                 UpdateStatus(true);
05468 
05469         return (unsigned short)cCap->wCapFileSize;
05470  }
05471 
05472 
05473 int vetDirectXInput2::getVideoFriendlyName(char* buffer)
05474  {
05475         if ( cCap->wachVideoFriendlyName[0] == 0 )
05476                 return VETRET_ILLEGAL_USE;
05477 
05478         char* str = Wide2Char(cCap->wachVideoFriendlyName);
05479         sprintf(buffer, "%s", str);
05480         free(str);
05481 
05482         return VETRET_OK;
05483  }
05484 
05485 unsigned long vetDirectXInput2::getVideoBitRate()
05486  {
05487          return (unsigned long)cCap->VideoBitRate;
05488  }
05489 
05490 unsigned long vetDirectXInput2::getAudioBitRate()
05491  {
05492          return (unsigned long)cCap->AudioBitRate;
05493  }
05494 
05495 int vetDirectXInput2::getAudioFriendlyName(char* buffer)
05496  {
05497         if ( cCap->wachAudioFriendlyName[0] == 0 )
05498                 return VETRET_ILLEGAL_USE;
05499 
05500         char* str = Wide2Char(cCap->wachAudioFriendlyName);
05501         sprintf(buffer, "%s", str);
05502         free(str);
05503 
05504         return VETRET_OK;
05505  }
05506 
05507 
05514 const char* vetDirectXInput2::getDeviceVideoDescription(int device)
05515  {
05516   // List available Devices once
05517   if (cCap->iNumVCapDevices == 0)
05518   {
05519     enumerateDevices();
05520 
05521     if (cCap->iNumVCapDevices == 0)
05522       return NULL;
05523   }
05524 
05525   if (device >= cCap->iNumVCapDevices)
05526     return NULL;
05527 
05528   return deviceVideoDesc[device];
05529  }
05530 
05531 
05538 const char* vetDirectXInput2::getDeviceAudioDescription(int device)
05539  {
05540   // List available Devices once
05541   if (cCap->iNumACapDevices == 0)
05542   {
05543     enumerateDevices();
05544 
05545     if (cCap->iNumACapDevices == 0)
05546       return NULL;
05547   }
05548 
05549   if (device >= cCap->iNumACapDevices)
05550     return NULL;
05551 
05552   return deviceAudioDesc[device];
05553  }
05554 
05555 
05556 int vetDirectXInput2::getDeviceVideoCount(void)
05557  {
05558          return cCap->iNumVCapDevices;
05559  }
05560 int vetDirectXInput2::getDeviceAudioCount(void)
05561  {
05562          return cCap->iNumACapDevices;
05563  }
05564 
05565 void vetDirectXInput2::setErrorMessagesEnabled(bool enable)
05566  {
05567          cCap->displayErrorMessages = enable;
05568  }
05569 
05570 void vetDirectXInput2::doUpdatePreviewWindow()
05571  {
05572         ResizeWindow(cCap->ghwndApp, width, height);
05573  }
05574 
05575 void vetDirectXInput2::setAutoUpdatePreviewWindowEnabled(bool enable)
05576  {
05577         cCap->autoUpdateWindow = enable;
05578  }
05579 
05580 bool vetDirectXInput2::isAutoUpdatePreviewWindowEnabled()
05581  {
05582         return cCap->autoUpdateWindow;
05583  }
05584 
05585 
05586 int vetDirectXInput2::showPreviewWindow(bool show)
05587  {
05588         if ( !cCap->pVW )
05589                 return VETRET_ILLEGAL_USE;
05590 
05591         if ( show )
05592 
05593                 cCap->pVW->put_Visible(-1);
05594         else
05595                 cCap->pVW->put_Visible(0);
05596 
05597         return VETRET_OK;
05598  }
05599 
05600 
05601 long vetDirectXInput2::getFreeSpaceLeft()
05602  {
05603         return GetFreeDiskSpaceInKB( cCap->szCaptureFile );
05604  }
05605 
05606 
05607 /*
05608 
05609 int vetDirectXInput2::getDShowGraphFilters(char* buffer)
05610  {
05611         IEnumFilters *pEnum = NULL;
05612         IBaseFilter *pFilter;
05613         ULONG cFetched;
05614 
05615          cCap->pFg->EnumFilters(&pEnum);
05616 
05617   IEnumFilters *pEnum = NULL;
05618 
05619   IBaseFilter *pFilter;
05620 
05621   ULONG cFetched;
05622 
05623   pGraph->EnumFilters(&pEnum);
05624 
05625 
05626   while(pEnum->Next(1, &pFilter, &cFetched) == S_OK)
05627 
05628   {
05629 
05630     FILTER_INFO FilterInfo;
05631 
05632     char szName[256];
05633 
05634     pFilter->QueryFilterInfo(&FilterInfo);
05635 
05636     WideCharToMultiByte(CP_ACP, 0, FilterInfo.achName, -1, szName, 256, 0, 0);
05637 
05638     fname= szName;
05639 
05640     names.push_back(fname);
05641 
05642 
05643     SAFE_RELEASE(FilterInfo.pGraph);
05644 
05645     SAFE_RELEASE(pFilter);
05646 
05647   }
05648 
05649 
05650 
05651   SAFE_RELEASE(pEnum);
05652 
05653 
05654 
05655   return names;
05656 
05657  }
05658 
05659 */
05660 
05661 
05666 
05667 
05668 // Tear down everything downstream of a given filter
05669 void NukeDownstream(vetDXCapture2* cCap, IBaseFilter *pf)
05670 {
05671     IPin *pP=0, *pTo=0;
05672     ULONG u;
05673     IEnumPins *pins = NULL;
05674     PIN_INFO pininfo;
05675 
05676     if (!pf)
05677         return;
05678 
05679     HRESULT hr = pf->EnumPins(&pins);
05680     pins->Reset();
05681 
05682     while(hr == NOERROR)
05683     {
05684         hr = pins->Next(1, &pP, &u);
05685         if(hr == S_OK && pP)
05686         {
05687             pP->ConnectedTo(&pTo);
05688             if(pTo)
05689             {
05690                 hr = pTo->QueryPinInfo(&pininfo);
05691                 if(hr == NOERROR)
05692                 {
05693                     if(pininfo.dir == PINDIR_INPUT)
05694                     {
05695                         NukeDownstream(cCap, pininfo.pFilter);
05696                         cCap->pFg->Disconnect(pTo);
05697                         cCap->pFg->Disconnect(pP);
05698                         cCap->pFg->RemoveFilter(pininfo.pFilter);
05699                     }
05700                     pininfo.pFilter->Release();
05701                 }
05702                 pTo->Release();
05703             }
05704             pP->Release();
05705         }
05706     }
05707 
05708     if(pins)
05709         pins->Release();
05710 }
05711 
05713 
05714 
05715 
05716 void IMonRelease(IMoniker *&pm)
05717 {
05718     if(pm)
05719     {
05720         pm->Release();
05721         pm = 0;
05722     }
05723 }
05724 
05725 
05726 
05727 
05728 
05733 
05734 
05735 
05736 /*----------------------------------------------------------------------------*\
05737 |   ErrMsg - Opens a Message box with a error message in it.  The user can     |
05738 |            select the OK button to continue                                  |
05739 \*----------------------------------------------------------------------------*/
05740 void ErrMsg(HWND ghwndApp, bool show, LPTSTR szFormat,...)
05741 {
05742         if ( !show )
05743                 return;
05744 
05745     static TCHAR szBuffer[2048]={0};
05746     const size_t NUMCHARS = sizeof(szBuffer) / sizeof(szBuffer[0]);
05747     const int LASTCHAR = NUMCHARS - 1;
05748 
05749     // Format the input string
05750     va_list pArgs;
05751     va_start(pArgs, szFormat);
05752 
05753     // Use a bounded buffer size to prevent buffer overruns.  Limit count to
05754     // character size minus one to allow for a NULL terminating character.
05755     _vsntprintf(szBuffer, NUMCHARS - 1, szFormat, pArgs);
05756     va_end(pArgs);
05757 
05758     // Ensure that the formatted string is NULL-terminated
05759     szBuffer[LASTCHAR] = TEXT('\0');
05760 
05761     MessageBox(ghwndApp, szBuffer, NULL,
05762                MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
05763 }
05764 
05765 
05767 
05768 
05769 
05770 void ResizeWindow(HWND ghwndApp, int w, int h)
05771 {
05772 
05773 //      SetWindowPos(ghwndApp, NULL, 0, 0, w, h,  SWP_NOZORDER | SWP_NOMOVE);
05774 
05775     RECT rcW, rcC;
05776     int xExtra, yExtra;
05777     int cyBorder = GetSystemMetrics(SM_CYBORDER);
05778 
05779     gnRecurse++;
05780 
05781     GetWindowRect(ghwndApp, &rcW);
05782     GetClientRect(ghwndApp, &rcC);
05783     xExtra = rcW.right - rcW.left - rcC.right;
05784     yExtra = rcW.bottom - rcW.top - rcC.bottom + cyBorder;
05785 
05786     rcC.right = w;
05787     rcC.bottom = h;
05788     SetWindowPos(ghwndApp, NULL, 0, 0, rcC.right + xExtra,
05789         rcC.bottom + yExtra, SWP_NOZORDER | SWP_NOMOVE);
05790 
05791     // we may need to recurse once.  But more than that means the window cannot
05792     // be made the size we want, trying will just stack fault.
05793     //
05794     if(gnRecurse == 1 && ((rcC.right + xExtra != rcW.right - rcW.left && w > GetSystemMetrics(SM_CXMIN)) ||
05795         (rcC.bottom + yExtra != rcW.bottom - rcW.top)))
05796         ResizeWindow(ghwndApp, w,h);
05797 
05798     gnRecurse--;
05799 
05800 }
05801 
05802 
05803 
05805 
05806 
05807 //
05808 // This function can be used when loading libraries in the Windows System
05809 // folder.  It queries for the system folder and prepends the path to the
05810 // name of the target library.  This helps to prevent spoofing of system DLLs.
05811 //
05812 // NOTE: Using this function may break apps who use Windows Fusion or who
05813 // explicitly replace Windows DLLs in the application's local folder.
05814 // If security is paramount, you can use this as a replacement for LoadLibrary().
05815 //
05816 HMODULE UtilLoadLibrary(LPCTSTR lpFileName)
05817 {
05818     TCHAR szFullPath[MAX_PATH];
05819     bool fSuccess = false;
05820 
05821     // Prevent buffer overflow by limiting size of library name
05822     int nLibLength = lstrlen(lpFileName);
05823     if((nLibLength > MAX_PATH) || (NULL == lpFileName))
05824         return NULL;
05825 
05826     int nSpaceAllowed = MAX_PATH - nLibLength - 4; // Allow for '\' and '\0'
05827     int nSpaceUsed = 0;
05828 
05829     // Initialize to a NULL string
05830     szFullPath[0] = TEXT('\0');
05831 
05832     // Read the Windows System directory
05833     nSpaceUsed = GetSystemDirectory(szFullPath, nSpaceAllowed);
05834 
05835     // If the function fails, the return value will be zero.
05836     // If the buffer isn't large enough, the function will return the size
05837     // of the buffer required to hold the path.  Check both failures.
05838     if((nSpaceUsed != 0) && (nSpaceUsed <= nSpaceAllowed))
05839     {
05840         // Now we have the Windows/System path with enough space left
05841         // to add the libary name and a terminating NULL character
05842         lstrcat(szFullPath, TEXT("\\\0"));
05843         lstrcat(szFullPath, lpFileName);
05844         lstrcat(szFullPath, TEXT("\0"));
05845         fSuccess = TRUE;
05846     }
05847 
05848     if(!fSuccess)
05849     {
05850         // An error occurred, so fallback to the default behavior by using
05851         // the NULL-terminated library name provided as a parameter.
05852         lstrcpyn(szFullPath, lpFileName, NUMELMS(szFullPath)-1);
05853         szFullPath[MAX_PATH - 1] = TEXT('\0');
05854     }
05855 
05856     return ((HMODULE) LoadLibrary(szFullPath));
05857 }
05858 
05859 
05860 
05861 
05862 
05863 
05864 
05866 
05867 
05868 
05869 DWORDLONG GetSize(LPCTSTR tach)
05870 {
05871     HANDLE hFile = CreateFile(tach, GENERIC_READ, FILE_SHARE_READ, 0,
05872         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
05873 
05874     if(hFile == INVALID_HANDLE_VALUE)
05875     {
05876         return 0;
05877     }
05878 
05879     DWORD dwSizeHigh;
05880     DWORD dwSizeLow = GetFileSize(hFile, &dwSizeHigh);
05881 
05882     DWORDLONG dwlSize = dwSizeLow + ((DWORDLONG)dwSizeHigh << 32);
05883 
05884     if(!CloseHandle(hFile))
05885     {
05886         dwlSize = 0;
05887     }
05888 
05889     return dwlSize;
05890 }
05891 
05892 
05893 
05895 
05896 //
05897 // GetFreeDiskSpace: Function to Measure Available Disk Space
05898 //
05899 long GetFreeDiskSpaceInKB(LPTSTR pFile)
05900 {
05901     DWORD dwFreeClusters, dwBytesPerSector, dwSectorsPerCluster, dwClusters;
05902     TCHAR RootName[MAX_PATH];
05903     LPTSTR ptmp=0;    //required arg
05904     ULARGE_INTEGER ulA, ulB, ulFreeBytes;
05905 
05906     // need to find path for root directory on drive containing this file.
05907     GetFullPathName(pFile, NUMELMS(RootName), RootName, &ptmp);
05908 
05909     // truncate this to the name of the root directory (how tedious)
05910     if(RootName[0] == '\\' && RootName[1] == '\\')
05911     {
05912         // path begins with  \\server\share\path so skip the first
05913         // three backslashes
05914         ptmp = &RootName[2];
05915         while(*ptmp && (*ptmp != '\\'))
05916         {
05917             ptmp++;
05918         }
05919         if(*ptmp)
05920         {
05921             // advance past the third backslash
05922             ptmp++;
05923         }
05924     }
05925     else
05926     {
05927         // path must be drv:\path
05928         ptmp = RootName;
05929     }
05930 
05931     // find next backslash and put a null after it
05932     while(*ptmp && (*ptmp != '\\'))
05933     {
05934         ptmp++;
05935     }
05936 
05937     // found a backslash ?
05938     if(*ptmp)
05939     {
05940         // skip it and insert null
05941         ptmp++;
05942         *ptmp = '\0';
05943     }
05944 
05945     // the only real way of finding out free disk space is calling
05946     // GetDiskFreeSpaceExA, but it doesn't exist on Win95
05947 
05948     HINSTANCE h = LoadLibrary(TEXT("kernel32.dll\0"));
05949     if(h)
05950     {
05951         typedef BOOL(WINAPI *MyFunc)(LPCTSTR RootName, PULARGE_INTEGER pulA, PULARGE_INTEGER pulB, PULARGE_INTEGER pulFreeBytes);
05952 
05953 #ifdef UNICODE
05954         MyFunc pfnGetDiskFreeSpaceEx = (MyFunc)GetProcAddress(h, "GetDiskFreeSpaceExW");
05955 #else
05956         MyFunc pfnGetDiskFreeSpaceEx = (MyFunc)GetProcAddress(h, "GetDiskFreeSpaceExA");
05957 #endif
05958         FreeLibrary(h);
05959 
05960         if(pfnGetDiskFreeSpaceEx)
05961         {
05962             if(!pfnGetDiskFreeSpaceEx(RootName, &ulA, &ulB, &ulFreeBytes))
05963                 return -1;
05964             else
05965                 return (long)(ulFreeBytes.QuadPart / 1024);
05966         }
05967     }
05968 
05969     if(!GetDiskFreeSpace(RootName, &dwSectorsPerCluster, &dwBytesPerSector,
05970                          &dwFreeClusters, &dwClusters))
05971         return (-1);
05972     else
05973         return(MulDiv(dwSectorsPerCluster * dwBytesPerSector, dwFreeClusters, 1024));
05974 }
05975 
05976 
05977 
05978 
05979 char* Wide2Char(WCHAR* wstr)
05980  {
05981   if (wstr)
05982   {
05983     int n = wcslen(wstr)+1;
05984     char* str = (char*)malloc(n);
05985     WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, n, NULL, NULL);
05986     return str;
05987   }
05988 
05989   return NULL;
05990  }
05991 

Generated on Tue Jan 24 11:59:01 2006 for VETLib by  doxygen 1.4.4