00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
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
00039
00040
00041
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
00062
00063
00064 #endif // !defined(AFX_STDAFX_H__08E7CDC6_7F58_11D2_8CF1_00A0C9441E20__INCLUDED)
00065
00070
00071
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 ( WINAPI *PUnregisterDeviceNotification)(
00084 IN HDEVNOTIFY Handle
00085 );
00086
00087 typedef HDEVNOTIFY ( WINAPI *PRegisterDeviceNotificationA)(
00088 IN HANDLE hRecipient,
00089 IN LPVOID NotificationFilter,
00090 IN DWORD Flags
00091 );
00092
00093 typedef HDEVNOTIFY ( 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
00135 #define WM_FGNOTIFY WM_USER+1
00136
00137
00138 #include "vetDirectXInput2.h"
00139
00140
00141
00151
00152
00153
00154
00155
00156
00157
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
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
00308
00309 HRESULT BuildMPEG2Segment( CComPtr<IBaseFilter> pFilter );
00310
00311
00312
00313 HRESULT RenderToMPEG2Demux( CComPtr<IPin> pPin );
00314
00315
00316
00317 HRESULT RenderToMPEG2Demux( CComPtr<IPin> pPin, const REGPINMEDIUM& pinMedium,
00318 CComPtr<IEnumMoniker> pEncoders );
00319
00320
00321
00322
00323 HRESULT RenderToMPEG2Demux( CComPtr<IPin> pPin, CComPtr<IEnumMoniker> pEncoders );
00324
00325
00326
00327 HRESULT ConnectEncoderToMPEG2Demux( CComPtr< IBaseFilter > pEncoder,
00328 const REGPINMEDIUM& pinMedium );
00329
00330
00331
00332 HRESULT ConnectMultiplexerToMPEG2Demux( CComPtr<IBaseFilter> pEncoder,
00333 CComPtr< IEnumMoniker > pMultiplexers );
00334 public:
00335
00336
00337
00338 HRESULT ConnectPin( CComPtr<IPin>, CComPtr< IBaseFilter > );
00339
00340
00341 HRESULT ConnectFilters(CComPtr<IBaseFilter> pUpFilter,
00342 CComPtr<IBaseFilter> pDownFilter);
00343 protected:
00344
00345
00346
00347
00348 HRESULT ConnectAudioPinToMultiplexer( CComPtr<IPin> pPin,
00349 CComPtr<IBaseFilter> pMultiplexer);
00350
00351
00352
00353
00354
00355 HRESULT GetEncodersByCategory( CComPtr<IEnumMoniker>& pEncoders );
00356 HRESULT GetEncodersByEnumerating( CComPtr<IPin> pPin, const REGPINMEDIUM& pinMedium,
00357 CComPtr<IEnumMoniker>& pEncoders );
00358
00359
00360
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
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398 #include "ksproxy.h"
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479 static
00480 BYTE
00481 Mpeg2ProgramVideo [] = {
00482 0x00, 0x00, 0x00, 0x00,
00483 0x00, 0x00, 0x00, 0x00,
00484 0xD0, 0x02, 0x00, 0x00,
00485 0xE0, 0x01, 0x00, 0x00,
00486 0x00, 0x00, 0x00, 0x00,
00487 0x00, 0x00, 0x00, 0x00,
00488 0x00, 0x00, 0x00, 0x00,
00489 0x00, 0x00, 0x00, 0x00,
00490 0x00, 0x09, 0x3D, 0x00,
00491 0x00, 0x00, 0x00, 0x00,
00492 0x63, 0x17, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
00493 0x00, 0x00, 0x00, 0x00,
00494 0x00, 0x00, 0x00, 0x00,
00495 0x04, 0x00, 0x00, 0x00,
00496 0x03, 0x00, 0x00, 0x00,
00497 0x00, 0x00, 0x00, 0x00,
00498 0x00, 0x00, 0x00, 0x00,
00499 0x28, 0x00, 0x00, 0x00,
00500 0xD0, 0x02, 0x00, 0x00,
00501 0xE0, 0x01, 0x00, 0x00,
00502 0x00, 0x00,
00503 0x00, 0x00,
00504 0x00, 0x00, 0x00, 0x00,
00505 0x00, 0x00, 0x00, 0x00,
00506 0xD0, 0x07, 0x00, 0x00,
00507 0x27, 0xCF, 0x00, 0x00,
00508 0x00, 0x00, 0x00, 0x00,
00509 0x00, 0x00, 0x00, 0x00,
00510 0x98, 0xF4, 0x06, 0x00,
00511 0x56, 0x00, 0x00, 0x00,
00512 0x02, 0x00, 0x00, 0x00,
00513 0x02, 0x00, 0x00, 0x00,
00514 0x00, 0x00, 0x00, 0x00,
00515
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
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
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659 hr = RenderStream(NULL, &MEDIATYPE_Video, pMPEG2Demux_, NULL, NULL );
00660
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
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
00751
00752
00753
00754
00755
00756
00757
00758
00759 BOOL ISampleCaptureGraphBuilder::IsMPEG2Pin( CComPtr<IPin> pPin )
00760 {
00761 if( !pPin )
00762 {
00763 return FALSE;
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,
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
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
00905
00906
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
00967
00968
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
01021
01022
01023
01024 HRESULT ISampleCaptureGraphBuilder::AddMPEG2Demux( )
01025 {
01026 if( pMPEG2Demux_ )
01027 {
01028
01029
01030
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;
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
01274
01275
01276
01277
01278
01279
01280
01281
01282 HRESULT
01283 ISampleCaptureGraphBuilder::RenderToMPEG2Demux(
01284 CComPtr<IPin> pPin,
01285 const REGPINMEDIUM& pinMedium,
01286 CComPtr<IEnumMoniker> pEncoders
01287 )
01288 {
01289
01290
01291
01292
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
01316
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
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
01369
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
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
01416
01417
01418 HRESULT hr = ConnectFilters(
01419 pEncoder,
01420 pMPEG2Demux_ );
01421 if( SUCCEEDED( hr ) )
01422 {
01423 return S_OK;
01424 }
01425
01426
01427
01428
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
01446
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
01520
01521 hr = ConnectFilters( pEncoder, pFilter );
01522 if( FAILED( hr ) )
01523 {
01524 graph_->RemoveFilter( pFilter );
01525 continue;
01526 }
01527
01528
01529
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
01562
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
01579
01580 hr = FindVideoPin( pFilter, pPin );
01581 if( FAILED( hr ) )
01582 {
01583 graph_->RemoveFilter( pMPEG2Demux_ );
01584 return hr;
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
01600
01601 return S_OK;
01602 }
01603
01604
01605
01606
01607
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
01644
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
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
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
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
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
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
01856
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
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
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
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
01973 CComPtr<IEnumPins> pEnumUpFilterPins ,
01974 pEnumDownFilterPins;
01975
01976 CComPtr<IPin> pUpFilterPin ,
01977 pDownFilterPin;
01978
01979 HRESULT hr = S_OK;
01980
01981
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
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
02002 hr = pUpFilterPin->QueryDirection( &pinDir );
02003 if( FAILED( hr ) || PINDIR_INPUT == pinDir )
02004 {
02005 continue;
02006 }
02007
02008
02009
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
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
02062
02063 BOOL bConnected = FALSE;
02064 ULONG nFetched = 0;
02065 CComPtr<IPin> pDownFilterPin;
02066
02067
02068
02069
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
02111 class SampleGrabberCB : public ISampleGrabberCB
02112 {
02113
02114 public:
02115
02116
02117
02118 long bufferSize;
02119 unsigned char *buffer;
02120 int frameId;
02121 bool frameWanted;
02122 HANDLE event;
02123
02124
02125
02126 STDMETHODIMP_(ULONG) AddRef() { return 2; }
02127 STDMETHODIMP_(ULONG) Release() { return 1; }
02128
02129
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
02146
02147 STDMETHODIMP SampleCB( double SampleTime, IMediaSample * pSample )
02148 {
02149 return 0;
02150 }
02151
02152
02153
02154
02155
02156 STDMETHODIMP BufferCB( double SampleTime, BYTE * pBuffer, long realBufferSize )
02157 {
02158
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
02224
02225 #define ABS(x) (((x) > 0) ? (x) : -(x))
02226
02227
02228
02229 #define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241 #ifdef DEBUG
02242 #define REGISTER_FILTERGRAPH
02243 #endif
02244
02245
02246
02247
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;
02263 ISampleCaptureGraphBuilder *pBuilder;
02264 IVideoWindow *pVW;
02265 IMediaEventEx *pME;
02266 IAMDroppedFrames *pDF;
02267 IAMVideoCompression *pVC;
02268 IAMVfwCaptureDialogs *pDlg;
02269 IAMStreamConfig *pASC;
02270 IAMStreamConfig *pVSC;
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;
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;
02332 long lDataCurrent;
02333
02334 bool fPreviewFaked;
02335
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
02356
02357 typedef LONG(PASCAL *LPWNDPROC)(HWND, UINT, WPARAM, LPARAM);
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379
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
02396
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
02410
02411
02412
02413
02414
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;
02468
02469
02470 cCap->fUseFrameRate = TRUE;
02471
02472 int units_per_frame = 666667;
02473 cCap->FrameRate = 10000000. / units_per_frame;
02474 cCap->FrameRate = (int)(cCap->FrameRate * 100) / 100.;
02475
02476
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
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
02545 TearDownGraph();
02546 FreeCapFilters();
02547
02548 }
02549
02550
02551
02553
02554
02555
02556
02557 int vetDirectXInput2::MakeBuilder()
02558 {
02559
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
02576
02577 int vetDirectXInput2::MakeGraph()
02578 {
02579
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
02606
02607
02608
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
02621 cCap->pVW->put_Owner(NULL);
02622 cCap->pVW->put_Visible(OAFALSE);
02623 cCap->pVW->Release();
02624 cCap->pVW = NULL;
02625 }
02626
02627
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
02636
02637
02638 #ifdef REGISTER_FILTERGRAPH
02639
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
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
02685
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
02705
02706
02707
02708
02709
02710
02711
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
02739
02740
02741 int vetDirectXInput2::InitCapFilters()
02742 {
02743 HRESULT hr=S_OK;
02744
02745 cCap->fCCAvail = FALSE;
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
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
02790
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
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
02815
02816
02817
02818
02819
02820
02821
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
02833
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
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
02855 if(cCap->pVSC && cCap->pVSC->GetFormat(&pmt) == S_OK)
02856 {
02857
02858 if(pmt->formattype == FORMAT_VideoInfo)
02859 {
02860
02861 width = HEADER(pmt->pbFormat)->biWidth;
02862 height = abs(HEADER(pmt->pbFormat)->biHeight);
02863
02864
02865
02866
02867 if ( cCap->autoUpdateWindow )
02868 ResizeWindow(cCap->ghwndApp, width, height);
02869
02870 }
02871 if(pmt->majortype != MEDIATYPE_Video)
02872 {
02873
02874
02875
02876
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
02890
02891
02892 hr = cCap->pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
02893 &MEDIATYPE_Video, cCap->pVCap,
02894 IID_IAMVfwCaptureDialogs, (void **)&cCap->pDlg);
02895
02896
02897
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
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
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
02937
02938 break;
02939
02940
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
02955 if(cCap->fCapAudioIsRelevant == FALSE)
02956 goto SkipAudio;
02957
02958
02959
02960
02961
02962
02963
02964
02965 if(cCap->pmAudio == 0)
02966 {
02967
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
02979 cCap->fCapAudio = FALSE;
02980 ErrMsg(cCap->ghwndApp, cCap->displayErrorMessages, TEXT("Cannot create audio capture filter"));
02981 goto SkipAudio;
02982 }
02983
02984
02985
02986
02987 {
02988 IPropertyBag *pBag;
02989
02990 cCap->wachAudioFriendlyName[0] = 0;
02991
02992
02993
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
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
03020
03021
03022
03023
03024
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
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;
03050 }
03051
03052
03053
03054
03055 return VETRET_OK;
03056
03057 InitCapFiltersFail:
03058 FreeCapFilters();
03059 return VETRET_INTERNAL_ERR;
03060 }
03061
03064
03065
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
03096
03097 int vetDirectXInput2::BuildCaptureGraph()
03098 {
03099 USES_CONVERSION;
03100
03101 HRESULT hr;
03102 AM_MEDIA_TYPE *pmt=0;
03103
03104
03105 if(cCap->fCaptureGraphBuilt)
03106 return VETRET_OK;
03107
03108
03109 if(cCap->fCapturing || cCap->fPreviewing)
03110 return VETRET_ILLEGAL_USE;
03111
03112
03113 if(cCap->pVCap == NULL)
03114 return VETRET_ILLEGAL_USE;
03115 if(cCap->pACap == NULL && cCap->fCapAudio)
03116 return VETRET_ILLEGAL_USE;
03117
03118
03119 if( cCap->fPreviewGraphBuilt )
03120 TearDownGraph();
03121
03122
03123
03124
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
03156
03157
03158
03159
03160
03161
03162
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
03181
03182
03183
03184
03185
03186
03187
03188
03189
03190
03191
03192
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
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
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
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
03267
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
03282 }
03283 }
03284
03285 if(cCap->fWantPreview)
03286 {
03287 hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_VBI, NULL,
03288 cCap->pVCap, NULL, NULL);
03289 }
03290 }
03291
03292
03293
03294
03295
03296
03297
03298
03299
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
03311
03312 RECT rc;
03313 cCap->pVW->put_Owner((OAHWND)cCap->ghwndApp);
03314 cCap->pVW->put_WindowStyle(WS_CHILD);
03315
03316 GetClientRect(cCap->ghwndApp, &rc);
03317
03318
03319
03320
03321 cCap->pVW->SetWindowPosition(0, 0, rc.right, rc.bottom);
03322
03323
03324
03325
03326
03327
03328
03329
03330 cCap->pVW->put_Visible(OATRUE);
03331
03332 }
03333 }
03334
03335
03336
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
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
03361
03362
03363 hr = cCap->pFg->QueryInterface(IID_IMediaEventEx, (void **)&cCap->pME);
03364 if(hr == NOERROR)
03365 {
03367 }
03368
03369
03370
03371
03372
03373
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
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
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
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 )
03474 {
03475
03476
03477 hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE,
03478 &MEDIATYPE_Video, cCap->pVCap, pAviDecFilter, cCap->pGrabberBaseFilter);
03479
03480 }
03481 else
03482 {
03483 hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE,
03484 NULL, cCap->pSmartTeeFilter, pAviDecFilter, cCap->pGrabberBaseFilter);
03485
03486
03487
03488
03489
03490
03491
03492
03493
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
03505
03506
03507
03508
03509
03510
03511
03512
03513
03514
03515
03516
03517 int vetDirectXInput2::BuildPreviewGraph()
03518 {
03519 HRESULT hr;
03520 AM_MEDIA_TYPE *pmt;
03521
03522
03523 if(cCap->fPreviewGraphBuilt)
03524 return VETRET_OK;
03525
03526
03527 if(cCap->fCapturing || cCap->fPreviewing)
03528 return VETRET_ILLEGAL_USE;
03529
03530
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
03538 if( cCap->fCaptureGraphBuilt )
03539 TearDownGraph();
03540
03541
03542
03543
03544
03545
03546
03547
03548
03549
03550
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
03573
03574
03575
03576
03577
03578
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
03596 cCap->fPreviewFaked = TRUE;
03597 }
03598 else if(hr != S_OK)
03599 {
03600
03601 hr = cCap->pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW,
03602 &MEDIATYPE_Video, cCap->pVCap, NULL, NULL);
03603 if(hr == VFW_S_NOPREVIEWPIN)
03604 {
03605
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
03618
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
03638
03639 if ( cCap->GrabbingEnabled )
03640 BuildGrabberGraph(false);
03641
03642 }
03643
03644
03645
03646
03647
03648
03649
03650
03651
03652
03653
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
03663 AM_MEDIA_TYPE * pmtDV;
03664
03665 if(cCap->pVSC && SUCCEEDED(cCap->pVSC->GetFormat(&pmtDV)))
03666 {
03667 if(pmtDV->formattype == FORMAT_DvInfo)
03668 {
03669
03670
03671
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
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);
03697 cCap->pVW->put_WindowStyle(WS_CHILD);
03698
03699
03700 GetClientRect(cCap->ghwndApp, &rc);
03701
03702
03703
03704
03705 cCap->pVW->SetWindowPosition(0, 0, rc.right, rc.bottom);
03706 cCap->pVW->put_Visible(OATRUE);
03707 }
03708
03709
03710
03711
03712
03713 if(cCap->pVSC && cCap->fUseFrameRate)
03714 {
03715 hr = cCap->pVSC->GetFormat(&pmt);
03716
03717
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
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
03741
03742
03743
03744
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
03755 cCap->fPreviewGraphBuilt = TRUE;
03756 return VETRET_OK;
03757 }
03758
03761
03762
03763
03764 int vetDirectXInput2::StartPreview()
03765 {
03766
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
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
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
03804
03805 int vetDirectXInput2::StopPreview()
03806 {
03807
03808 if(!cCap->fPreviewing)
03809 return VETRET_ILLEGAL_USE;
03810
03811
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
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
03843
03844 int vetDirectXInput2::StartCapture()
03845 {
03846 bool fHasStreamControl;
03847 HRESULT hr;
03848
03849
03850 if(cCap->fCapturing)
03851 {
03852 ErrMsg(cCap->ghwndApp, cCap->displayErrorMessages, TEXT("Error: Already Capturing!"));
03853 return VETRET_ILLEGAL_USE;
03854 }
03855
03856
03857 bool didPreview = cCap->fPreviewing;
03858 if(cCap->fPreviewing)
03859 StopPreview();
03860
03861
03862 if(cCap->fPreviewGraphBuilt)
03863 TearDownGraph();
03864
03865 BuildCaptureGraph();
03866
03867
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
03875
03876
03877
03878
03879 cCap->lDroppedBase = 0;
03880 cCap->lNotBase = 0;
03881
03882 REFERENCE_TIME start = MAX_TIME, stop = MAX_TIME;
03883
03884
03885 hr = cCap->pBuilder->ControlStream(&PIN_CATEGORY_CAPTURE, NULL,
03886 NULL, &start, NULL, 0, 0);
03887
03888
03889 fHasStreamControl = SUCCEEDED(hr);
03890
03891
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
03901
03902
03903
03904
03905
03906
03907 if(fHasStreamControl)
03908 hr = pMC->Run();
03909 else
03910 hr = pMC->Pause();
03911 if(FAILED(hr))
03912 {
03913
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
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
03936 hr = cCap->pBuilder->ControlStream(&PIN_CATEGORY_CAPTURE, NULL,
03937 NULL, NULL, &stop, 0, 0);
03938
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
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
03962 cCap->lCapStartTime = timeGetTime();
03963 cCap->lCapStopTime = 0;
03964
03965
03966
03967 UpdateStatus(true);
03968
03969 cCap->fCapturing = TRUE;
03970
03971 return VETRET_OK;
03972 }
03973
03975
03976
03977
03978 int vetDirectXInput2::StopCapture()
03979 {
03980
03981 if(!cCap->fCapturing)
03982 {
03983 ErrMsg(cCap->ghwndApp, cCap->displayErrorMessages, TEXT("Error: Start Capturing first!"));
03984 return VETRET_INTERNAL_ERR;
03985 }
03986
03987
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
04002 cCap->lCapStopTime = timeGetTime();
04003
04004
04005
04006
04007
04008 UpdateStatus(true);
04009
04010 cCap->fCapturing = FALSE;
04011
04012
04013
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
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
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
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
04163 {
04164 HMODULE hmodUser = GetModuleHandle(TEXT("user32.dll"));
04165 ASSERT(hmodUser);
04166 gpUnregisterDeviceNotification = (PUnregisterDeviceNotification)
04167 GetProcAddress(hmodUser, "UnregisterDeviceNotification");
04168
04169
04170 gpRegisterDeviceNotification = (PRegisterDeviceNotification)
04171 GetProcAddress(hmodUser,
04172 #ifdef UNICODE
04173 "RegisterDeviceNotificationW"
04174 #else
04175 "RegisterDeviceNotificationA"
04176 #endif
04177 );
04178
04179
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
04202 if (!cCap->pDlg)
04203 {
04204 return VETRET_ILLEGAL_USE;
04205 }
04206
04207
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
04220
04221
04222
04223 if(hrD == VFW_E_CANNOT_CONNECT)
04224 {
04225 DbgLog((LOG_TRACE,1,TEXT("DIALOG CORRUPTED GRAPH!")));
04226 TearDownGraph();
04227
04228 return VETRET_INTERNAL_ERR;
04229 }
04230
04231
04232 if(cCap->pVSC)
04233 {
04234 AM_MEDIA_TYPE *pmt;
04235
04236 hrD = cCap->pVSC->GetFormat(&pmt);
04237
04238
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
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
04361
04362
04363
04364
04365
04366
04367
04368
04369 HRESULT hr;
04370
04371
04372
04373
04374
04375
04376
04377
04378
04379
04380
04381 if(cCap->fCaptureGraphBuilt || cCap->fPreviewGraphBuilt)
04382 {
04383 DbgLog((LOG_TRACE,1,TEXT("Tear down graph for dialog")));
04384 TearDownGraph();
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
04411
04412
04413 if(cCap->pVSC)
04414 {
04415 AM_MEDIA_TYPE *pmt;
04416
04417 hr = cCap->pVSC->GetFormat(&pmt);
04418
04419
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
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
04443
04444
04445 return 0;
04446 }
04447
04448
04449
04451
04452
04453
04454
04455 int vetDirectXInput2::AllocCaptureFile(unsigned short fileSize_mb)
04456 {
04457 USES_CONVERSION;
04458
04459
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
04469
04470
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
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
04502
04503
04504 #ifdef UNICODE
04505
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
04516 if( AllocCaptureFile() )
04517 return VETRET_INTERNAL_ERR;
04518 }
04519
04520
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
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
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
04573
04574
04575
04576
04577 bool didPrev = cCap->fPreviewing;
04578 if(cCap->fPreviewing)
04579 StopPreview();
04580
04581
04582
04583 if(cCap->pVSC)
04584 {
04585 AM_MEDIA_TYPE *pmt;
04586 hr = cCap->pVSC->GetFormat(&pmt);
04587
04588
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)
04613 StartPreview();
04614
04615 return VETRET_OK;
04616 }
04617
04618
04619
04620
04621
04622
04623
04624
04625
04626
04627
04628
04629
04630
04631
04632
04633
04634
04635
04636
04637
04638
04639
04640
04641
04642
04643
04644
04645
04646
04647
04648
04649
04650
04651
04652
04653
04654
04655
04656
04657
04658
04659
04660
04661
04662
04663
04664
04665
04666
04667
04668
04669
04670
04671
04672
04673
04674
04675
04676
04677
04678
04679
04680
04681
04682
04683
04684
04685
04686
04687
04688
04689
04690
04693
04694
04695
04696
04697 void vetDirectXInput2::UpdateStatus(bool fAllStats)
04698 {
04699 HRESULT hr;
04700
04701
04702
04703
04704
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
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
04737
04738
04739
04740
04741 return;
04742 }
04743
04744
04745
04746
04747
04748
04749
04750
04751 hr = cCap->pDF->GetAverageFrameSize(&cCap->lAvgFrameSizeCurrent);
04752 if(hr != S_OK)
04753 return;
04754
04755
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
04776
04777
04778
04779
04780
04781
04782
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
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
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)
04864 {
04865 BuildPreviewGraph();
04866 StartPreview();
04867 }
04868
04869 }
04870
04871
04872
04873
04874
04875
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
04883
04884
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
04890 return VETRET_OK;
04891 }
04892 }
04893 }
04894
04895
04896
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
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
04971
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
05017
05018
05019
05020
05021
05022
05023
05024
05025
05026
05027
05028
05029
05030
05031
05032
05033
05034
05035
05036
05037
05038
05039
05040
05041
05042
05043
05044
05045
05046
05047
05048
05049
05050
05051
05052
05053
05054
05055
05056
05057
05058
05059
05060
05061
05062
05063
05064
05065
05066
05067
05068
05069
05070
05071
05072
05073
05074
05075
05076
05077
05078
05079
05080
05081
05082
05083
05084
05085
05086
05087
05088
05089
05090
05091
05092
05093
05094
05095
05096
05097
05098
05099
05100
05101
05102
05103
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
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++);
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
05165
05166
05167
05168
05169
05170
05171
05172
05173
05174
05175
05176
05177
05178
05179
05180
05181
05182
05183
05184
05185
05186
05187
05188
05189
05190
05191
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
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)
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
05377 cCap->fCapAudio = enable;
05378
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
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
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
05610
05611
05612
05613
05614
05615
05616
05617
05618
05619
05620
05621
05622
05623
05624
05625
05626
05627
05628
05629
05630
05631
05632
05633
05634
05635
05636
05637
05638
05639
05640
05641
05642
05643
05644
05645
05646
05647
05648
05649
05650
05651
05652
05653
05654
05655
05656
05657
05658
05659
05660
05661
05666
05667
05668
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
05738
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
05750 va_list pArgs;
05751 va_start(pArgs, szFormat);
05752
05753
05754
05755 _vsntprintf(szBuffer, NUMCHARS - 1, szFormat, pArgs);
05756 va_end(pArgs);
05757
05758
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
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
05792
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
05809
05810
05811
05812
05813
05814
05815
05816 HMODULE UtilLoadLibrary(LPCTSTR lpFileName)
05817 {
05818 TCHAR szFullPath[MAX_PATH];
05819 bool fSuccess = false;
05820
05821
05822 int nLibLength = lstrlen(lpFileName);
05823 if((nLibLength > MAX_PATH) || (NULL == lpFileName))
05824 return NULL;
05825
05826 int nSpaceAllowed = MAX_PATH - nLibLength - 4;
05827 int nSpaceUsed = 0;
05828
05829
05830 szFullPath[0] = TEXT('\0');
05831
05832
05833 nSpaceUsed = GetSystemDirectory(szFullPath, nSpaceAllowed);
05834
05835
05836
05837
05838 if((nSpaceUsed != 0) && (nSpaceUsed <= nSpaceAllowed))
05839 {
05840
05841
05842 lstrcat(szFullPath, TEXT("\\\0"));
05843 lstrcat(szFullPath, lpFileName);
05844 lstrcat(szFullPath, TEXT("\0"));
05845 fSuccess = TRUE;
05846 }
05847
05848 if(!fSuccess)
05849 {
05850
05851
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
05898
05899 long GetFreeDiskSpaceInKB(LPTSTR pFile)
05900 {
05901 DWORD dwFreeClusters, dwBytesPerSector, dwSectorsPerCluster, dwClusters;
05902 TCHAR RootName[MAX_PATH];
05903 LPTSTR ptmp=0;
05904 ULARGE_INTEGER ulA, ulB, ulFreeBytes;
05905
05906
05907 GetFullPathName(pFile, NUMELMS(RootName), RootName, &ptmp);
05908
05909
05910 if(RootName[0] == '\\' && RootName[1] == '\\')
05911 {
05912
05913
05914 ptmp = &RootName[2];
05915 while(*ptmp && (*ptmp != '\\'))
05916 {
05917 ptmp++;
05918 }
05919 if(*ptmp)
05920 {
05921
05922 ptmp++;
05923 }
05924 }
05925 else
05926 {
05927
05928 ptmp = RootName;
05929 }
05930
05931
05932 while(*ptmp && (*ptmp != '\\'))
05933 {
05934 ptmp++;
05935 }
05936
05937
05938 if(*ptmp)
05939 {
05940
05941 ptmp++;
05942 *ptmp = '\0';
05943 }
05944
05945
05946
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