00001
00015
00016
00017 #include "vetDirectXInput.h"
00018
00019
00020 #include <dshow.h>
00021 #include <qedit.h>
00022
00023
00024 #define _WIN32_WINNT 0x0500 // Because of TryEnterCriticalSection ???????????????????????
00025
00026
00027
00028
00029 #define SafeRelease(p) { if( (p) != 0 ) { (p)->Release(); (p)= NULL; } }
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 class imTrackingGrabberCB : public ISampleGrabberCB
00067 {
00068 protected:
00069 int m_Width, m_Height;
00070 bool m_newImageFlag;
00071 unsigned char *m_ImageData;
00072 CRITICAL_SECTION m_sect;
00073 HANDLE m_imageReady;
00074
00075 public:
00076
00077 imTrackingGrabberCB();
00078 ~imTrackingGrabberCB();
00079
00080 STDMETHODIMP SampleCB(double SampleTime, IMediaSample *pSample);
00081 STDMETHODIMP BufferCB(double SampleTime, BYTE *pBuffer, long BufferLen) {return E_NOTIMPL;}
00082 STDMETHODIMP_(ULONG) AddRef() {return 2;}
00083 STDMETHODIMP_(ULONG) Release() {return 1;}
00084 STDMETHODIMP QueryInterface(REFIID riid, void ** ppv);
00085
00086 void SetImageSize(int width, int height);
00087 int GetImage(unsigned char* data, int color_mode, int timeout);
00088
00089 };
00090
00091 imTrackingGrabberCB::imTrackingGrabberCB()
00092 {
00093 InitializeCriticalSection(&m_sect);
00094 m_newImageFlag = 0;
00095 m_ImageData = NULL;
00096 m_imageReady = CreateEvent(NULL, FALSE, TRUE, NULL);
00097 }
00098
00099 imTrackingGrabberCB::~imTrackingGrabberCB()
00100 {
00101 CloseHandle(m_imageReady);
00102 EnterCriticalSection(&m_sect);
00103 DeleteCriticalSection(&m_sect);
00104 if (m_ImageData)
00105 delete m_ImageData;
00106 }
00107
00108 STDMETHODIMP imTrackingGrabberCB::QueryInterface(REFIID riid, void ** ppv)
00109 {
00110 if( riid == IID_ISampleGrabberCB || riid == IID_IUnknown )
00111 {
00112 *ppv = (void *) static_cast<ISampleGrabberCB*> (this);
00113 return NOERROR;
00114 }
00115
00116 return E_NOINTERFACE;
00117 }
00118
00119 void imTrackingGrabberCB::SetImageSize(int width, int height)
00120 {
00121 EnterCriticalSection(&m_sect);
00122
00123
00124
00125 int new_size = width * height * 3;
00126
00127 if (!m_ImageData)
00128 {
00129 m_ImageData = (BYTE*)calloc(new_size, 1);
00130 m_Width = width;
00131 m_Height = height;
00132 }
00133
00134 if (m_Width*m_Height < new_size)
00135 m_ImageData = (BYTE*)realloc(m_ImageData, new_size);
00136
00137 m_Width = width;
00138 m_Height = height;
00139
00140 LeaveCriticalSection(&m_sect);
00141 }
00142
00143 STDMETHODIMP imTrackingGrabberCB::SampleCB(double, IMediaSample *pSample)
00144 {
00145 if (!m_ImageData) return S_OK;
00146
00147 EnterCriticalSection(&m_sect);
00148
00149 int size = pSample->GetSize();
00150 if (size > m_Width*m_Height*3)
00151 {
00152 LeaveCriticalSection(&m_sect);
00153 return S_OK;
00154 }
00155
00156 BYTE *pData;
00157 pSample->GetPointer(&pData);
00158 CopyMemory(m_ImageData, pData, size);
00159 m_newImageFlag = 1;
00160
00161 LeaveCriticalSection(&m_sect);
00162
00163 SetEvent(m_imageReady);
00164
00165 return S_OK;
00166 }
00167
00168 int imTrackingGrabberCB::GetImage(unsigned char* data, int color_mode, int timeout)
00169 {
00170 unsigned char* src_data = m_ImageData + m_Width * m_Height * 3;
00171 unsigned char* dst_data = data;
00172
00173 EnterCriticalSection(&m_sect);
00174
00175 for (int i = 0; i < m_Width*m_Height; i++)
00176 {
00177 *(dst_data+2) = *src_data--;
00178 *dst_data = *src_data--;
00179 *(dst_data+1) = *src_data--;
00180 dst_data += 3;
00181 }
00182
00183 LeaveCriticalSection(&m_sect);
00184
00185 return VETRET_OK;
00186 }
00187
00188
00189
00190
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 struct vetDXCapture
00204 {
00205 int registered_graph,
00206 live,
00207 device;
00208
00209
00210
00211
00212
00213 IGraphBuilder* filter_builder;
00214 ICaptureGraphBuilder2* capture_graph_builder;
00215 IBaseFilter* capture_filter;
00216 IBaseFilter* grabber_filter;
00217 IBaseFilter* null_filter;
00218 ISampleGrabber* sample_grabber;
00219 IMediaControl* media_control;
00220 IBaseFilter* overlay_renderer;
00221 IBaseFilter *overlay_mixer;
00222
00223 IAMVideoProcAmp* video_prop;
00224 IAMCameraControl* camera_prop;
00225 IAMVideoControl* videoctrl_prop;
00226
00227 imTrackingGrabberCB* sample_callback;
00228
00229 int format_count;
00230 int format_current;
00231 int format_map[50];
00232
00233
00234 ISpecifyPropertyPages *pSpec;
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 };
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 #ifdef INCLUDE_VFW_DEVICES
00275 #define CATEGORY_FLAG 0
00276 #else
00277 #define CATEGORY_FLAG CDEF_DEVMON_FILTER|CDEF_DEVMON_PNP_DEVICE
00278 #endif
00279
00280 IBaseFilter* vetGetDevice(int device)
00281 {
00282
00283 ICreateDevEnum *pDevEnum = NULL;
00284 IEnumMoniker *pEnum = NULL;
00285
00286
00287 HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
00288 CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
00289 reinterpret_cast<void**>(&pDevEnum));
00290 if (FAILED(hr)) return NULL;
00291
00292
00293 hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, CATEGORY_FLAG);
00294 if (FAILED(hr) || !pEnum)
00295 {
00296 pDevEnum->Release();
00297 return NULL;
00298 }
00299
00300 IMoniker *pMoniker = NULL;
00301 int d = 0;
00302 while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
00303 {
00304 if (d == device)
00305 {
00306
00307
00308 IBaseFilter *capture_filter = NULL;
00309 hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&capture_filter);
00310 if (SUCCEEDED(hr))
00311 {
00312 pMoniker->Release();
00313 pEnum->Release();
00314 pDevEnum->Release();
00315 return capture_filter;
00316 }
00317 else
00318 {
00319 pMoniker->Release();
00320 break;
00321 }
00322 }
00323
00324 pMoniker->Release();
00325 d++;
00326 }
00327
00328 pEnum->Release();
00329 pDevEnum->Release();
00330 return NULL;
00331 }
00332
00333
00334 IPin* vetGetPin(IBaseFilter* pFilter, PIN_DIRECTION dir)
00335 {
00336 IEnumPins* pEnumPins = NULL;
00337 IPin* pPin = NULL;
00338
00339 pFilter->EnumPins(&pEnumPins);
00340 if(!pEnumPins)
00341 return NULL;
00342
00343 for(;;)
00344 {
00345 ULONG cFetched = 0;
00346 PIN_DIRECTION pinDir = PIN_DIRECTION(-1);
00347 pPin = 0;
00348
00349 if (FAILED(pEnumPins->Next(1, &pPin, &cFetched)))
00350 {
00351 pEnumPins->Release();
00352 return NULL;
00353 }
00354
00355 if(cFetched == 1 && pPin != 0)
00356 {
00357 pPin->QueryDirection(&pinDir);
00358 if(pinDir == dir) break;
00359 pPin->Release();
00360 }
00361 }
00362
00363 pEnumPins->Release();
00364 return pPin;
00365 }
00366
00367 void vetNukeDownstream(IGraphBuilder* filter_builder, IBaseFilter *filter)
00368 {
00369 IPin *pPin=0, *pPinTo=0;
00370 IEnumPins *pEnumPins = NULL;
00371 PIN_INFO pininfo;
00372
00373 HRESULT hr = filter->EnumPins(&pEnumPins);
00374 if (FAILED(hr)) return;
00375
00376 pEnumPins->Reset();
00377
00378 while(hr == NOERROR)
00379 {
00380 hr = pEnumPins->Next(1, &pPin, NULL);
00381 if(hr == S_OK && pPin)
00382 {
00383 pPin->ConnectedTo(&pPinTo);
00384 if(pPinTo)
00385 {
00386 hr = pPinTo->QueryPinInfo(&pininfo);
00387 if(hr == NOERROR)
00388 {
00389 if(pininfo.dir == PINDIR_INPUT)
00390 {
00391 vetNukeDownstream(filter_builder, pininfo.pFilter);
00392 filter_builder->Disconnect(pPinTo);
00393 filter_builder->Disconnect(pPin);
00394 filter_builder->RemoveFilter(pininfo.pFilter);
00395 }
00396
00397 pininfo.pFilter->Release();
00398 }
00399
00400 pPinTo->Release();
00401 }
00402
00403 pPin->Release();
00404 }
00405 }
00406
00407 pEnumPins->Release();
00408
00409 }
00410
00411 int vetDisconnectFilters(IGraphBuilder* filter_builder, IBaseFilter* source, IBaseFilter* destiny)
00412 {
00413 IPin *pOut = vetGetPin(source, PINDIR_OUTPUT);
00414 IPin *pIn = vetGetPin(destiny, PINDIR_INPUT);
00415 HRESULT hr = filter_builder->Disconnect(pOut);
00416 hr = filter_builder->Disconnect(pIn);
00417 pOut->Release();
00418 pIn->Release();
00419
00420 if (FAILED(hr))
00421 return VETRET_INTERNAL_ERR;
00422
00423 return VETRET_OK;
00424 }
00425
00426 int vetDisconnectFilterPin(IGraphBuilder* filter_builder, IBaseFilter* filter, PIN_DIRECTION dir)
00427 {
00428 IPin *pIn = vetGetPin(filter, dir);
00429 IPin *pOut;
00430 pIn->ConnectedTo(&pOut);
00431
00432 HRESULT hr = filter_builder->Disconnect(pIn);
00433 pIn->Release();
00434
00435 if (FAILED(hr))
00436 {
00437 if (pOut)
00438 pOut->Release();
00439 return VETRET_INTERNAL_ERR;
00440 }
00441
00442 if (pOut)
00443 {
00444 hr = filter_builder->Disconnect(pOut);
00445 pOut->Release();
00446
00447 if (FAILED(hr))
00448 return VETRET_INTERNAL_ERR;
00449 }
00450
00451 return VETRET_OK;
00452 }
00453
00454 int vetConnectFilters(IGraphBuilder* filter_builder, IBaseFilter* source, IBaseFilter* destiny, int direct)
00455 {
00456 HRESULT hr;
00457
00458 IPin *pOut = vetGetPin(source, PINDIR_OUTPUT);
00459 IPin *pIn = vetGetPin(destiny, PINDIR_INPUT);
00460
00461 if (direct)
00462 hr = filter_builder->ConnectDirect(pOut, pIn, NULL);
00463 else
00464 hr = filter_builder->Connect(pOut, pIn);
00465
00466 pOut->Release();
00467 pIn->Release();
00468
00469 if (FAILED(hr))
00470 return VETRET_INTERNAL_ERR;
00471
00472 return VETRET_OK;
00473 }
00474
00475 DWORD vetAddGraphToRot(IUnknown *pUnkGraph)
00476 {
00477 IMoniker * pMoniker;
00478 IRunningObjectTable *pROT;
00479 WCHAR wsz[128];
00480 HRESULT hr;
00481
00482 if (FAILED(GetRunningObjectTable(0, &pROT)))
00483 return 0;
00484
00485 wsprintfW(wsz, L"FilterGraph %08x pid %08x\0", (DWORD_PTR)pUnkGraph, GetCurrentProcessId());
00486
00487 hr = CreateItemMoniker(L"!", wsz, &pMoniker);
00488 if (SUCCEEDED(hr))
00489 {
00490 DWORD dwRegister;
00491 hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pUnkGraph, pMoniker, &dwRegister);
00492 pROT->Release();
00493
00494 pMoniker->Release();
00495
00496 if (SUCCEEDED(hr))
00497 return dwRegister;
00498 }
00499
00500 pROT->Release();
00501 return 0;
00502 }
00503
00504 void vetRemoveGraphFromRot(DWORD pdwRegister)
00505 {
00506 IRunningObjectTable *pROT;
00507
00508 if (SUCCEEDED(GetRunningObjectTable(0, &pROT)))
00509 {
00510 pROT->Revoke(pdwRegister);
00511 pROT->Release();
00512 }
00513 }
00514
00515
00516
00517
00518
00519
00520 IAMStreamConfig* vetGetStreamConfig(vetDXCapture* vc)
00521 {
00522 IAMStreamConfig *pSC = NULL;
00523 if (FAILED(vc->capture_graph_builder->FindInterface(&PIN_CATEGORY_CAPTURE,
00524 &MEDIATYPE_Video, vc->capture_filter, IID_IAMStreamConfig, (void **)&pSC)))
00525 return NULL;
00526
00527 return pSC;
00528 }
00529
00530
00531 void vetDeleteMediaType(AM_MEDIA_TYPE *pmt)
00532 {
00533 CoTaskMemFree((PVOID)pmt->pbFormat);
00534 CoTaskMemFree(pmt);
00535 }
00536
00537
00538
00539
00540
00541
00542
00543 static void vetGetFormatName(GUID subtype, char* desc)
00544 {
00545 #define NUM_FORM 7
00546 typedef struct _guid2name {
00547 char* name;
00548 const GUID* subtype;
00549 } guid2name;
00550 static guid2name map_table[NUM_FORM] = {
00551 {"RGB1",&MEDIASUBTYPE_RGB1},
00552 {"RGB4",&MEDIASUBTYPE_RGB4},
00553 {"RGB8",&MEDIASUBTYPE_RGB8},
00554 {"RGB565",&MEDIASUBTYPE_RGB565},
00555 {"RGB555",&MEDIASUBTYPE_RGB555},
00556 {"RGB24",&MEDIASUBTYPE_RGB24},
00557 {"RGB32",&MEDIASUBTYPE_RGB32}
00558 };
00559
00560 for (int i = 0; i < NUM_FORM; i++)
00561 {
00562 if (*(map_table[i].subtype) == subtype)
00563 {
00564 strcpy(desc, map_table[i].name);
00565 return;
00566 }
00567 }
00568
00569 desc[0] = (char)(subtype.Data1);
00570 desc[1] = (char)(subtype.Data1 >> 8);
00571 desc[2] = (char)(subtype.Data1 >> 16);
00572 desc[3] = (char)(subtype.Data1 >> 32);
00573 desc[4] = 0;
00574 }
00575
00576
00577
00578
00579
00580 static IIPDVDec* vetGetDVDecoder(vetDXCapture* vc)
00581 {
00582 IIPDVDec *pDV = NULL;
00583 HRESULT hr = vc->capture_graph_builder->FindInterface(NULL,
00584 &MEDIATYPE_Video, vc->capture_filter, IID_IIPDVDec, (void **)&pDV);
00585 if(FAILED(hr))
00586 return NULL;
00587
00588 return pDV;
00589 }
00590
00591
00592
00593
00597
00598
00599
00600
00608 vetDirectXInput::vetDirectXInput(int device) : vetInput(0)
00609 {
00610 INFO("vetDirectXInput::vetDirectXInput(float fps) : vetInput(fps) [CONTRUCTOR]")
00611
00612 deviceCount = 0;
00613 enumerateDevices();
00614
00615 cCap = (vetDXCapture*)malloc(sizeof(vetDXCapture));
00616 memset(cCap, 0, sizeof(vetDXCapture));
00617
00618 cCap->sample_callback = NULL;
00619 cCap->device = -1;
00620
00621 connectTo(device);
00622 }
00623
00624
00625 vetDirectXInput::vetDirectXInput(int device, float fps) : vetInput(fps)
00626 {
00627 INFO("vetDirectXInput::vetDirectXInput(float fps) : vetInput(fps) [CONTRUCTOR]")
00628
00629 deviceCount = 0;
00630 enumerateDevices();
00631
00632 cCap = (vetDXCapture*)malloc(sizeof(vetDXCapture));
00633 memset(cCap, 0, sizeof(vetDXCapture));
00634
00635 cCap->sample_callback = NULL;
00636 cCap->device = -1;
00637
00638 connectTo(device);
00639 }
00640
00645 vetDirectXInput::~vetDirectXInput()
00646 {
00647
00648 #ifdef REGISTER_FILTERGRAPH
00649 if (vc->registered_graph)
00650 vc_RemoveGraphFromRot(vc->registered_graph);
00651 #endif
00652
00653 disconnect();
00654
00655 if (cCap->sample_callback != NULL)
00656 delete cCap->sample_callback;
00657
00658 SafeRelease(cCap->overlay_mixer);
00659 SafeRelease(cCap->overlay_renderer);
00660 SafeRelease(cCap->media_control);
00661 SafeRelease(cCap->sample_grabber);
00662
00663 if (cCap->null_filter != NULL)
00664 cCap->null_filter->Release();
00665
00666 if (cCap->grabber_filter != NULL)
00667 cCap->grabber_filter->Release();
00668
00669 if (cCap->filter_builder != NULL)
00670 cCap->filter_builder->Release();
00671
00672 if (cCap->capture_graph_builder != NULL)
00673 cCap->capture_graph_builder->Release();
00674
00675 free(cCap);
00676 }
00677
00680
00681 VETRESULT vetDirectXInput::initCaptureGraphBuilder(vetDXCapture* vdx)
00682 {
00683 HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER,
00684 IID_ICaptureGraphBuilder2, reinterpret_cast<void**>(&vdx->capture_graph_builder));
00685 if (FAILED(hr))
00686 return VETRET_INTERNAL_ERR;
00687
00688 hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
00689 IID_IGraphBuilder, reinterpret_cast<void**>(&vdx->filter_builder));
00690 if (FAILED(hr))
00691 return VETRET_INTERNAL_ERR;
00692
00693 hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
00694 IID_IBaseFilter, reinterpret_cast<void**>(&vdx->grabber_filter));
00695 if (FAILED(hr))
00696 return VETRET_INTERNAL_ERR;
00697
00698 hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER,
00699 IID_IBaseFilter, reinterpret_cast<void**>(&vdx->null_filter));
00700 if (FAILED(hr))
00701 return VETRET_INTERNAL_ERR;
00702
00703
00704 vdx->capture_graph_builder->SetFiltergraph(vdx->filter_builder);
00705
00706 hr = vdx->filter_builder->QueryInterface(IID_IMediaControl,(void**)&vdx->media_control);
00707 hr = vdx->grabber_filter->QueryInterface(IID_ISampleGrabber, (void **)&vdx->sample_grabber);
00708
00709
00710
00711
00712 AM_MEDIA_TYPE mt;
00713 ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
00714
00715 mt.majortype = MEDIATYPE_Video;
00716 mt.subtype = MEDIASUBTYPE_RGB24;
00717
00718 vdx->sample_grabber->SetMediaType(&mt);
00719 vdx->sample_grabber->SetOneShot(FALSE);
00720 vdx->sample_grabber->SetBufferSamples(FALSE);
00721
00722 vdx->sample_callback = new imTrackingGrabberCB();
00723
00724 hr = vdx->filter_builder->AddFilter(vdx->grabber_filter, L"imSampleGrabber");
00725 hr = vdx->filter_builder->AddFilter(vdx->null_filter, L"imNullRenderer");
00726
00727
00728 IMediaFilter* pMediaFilter = NULL;
00729 vdx->filter_builder->QueryInterface(IID_IMediaFilter, (void**)&pMediaFilter);
00730 pMediaFilter->SetSyncSource(NULL);
00731 pMediaFilter->Release();
00732
00733 #ifdef REGISTER_FILTERGRAPH
00734 vdx->registered_graph = vc_AddGraphToRot(vdx->filter_builder);
00735 #endif
00736
00737
00738 return VETRET_OK;
00739 }
00740
00743
00751 VETRESULT vetDirectXInput::connect()
00752 {
00753 if (deviceCount == 0)
00754 {
00755 enumerateDevices();
00756 if (deviceCount == 0)
00757 return VETRET_ILLEGAL_USE;
00758 }
00759
00760 if (cCap->device == -1 || cCap->device >= deviceCount)
00761 return VETRET_ILLEGAL_USE;
00762
00763 return connectTo(cCap->device);
00764 }
00765
00766
00775 VETRESULT vetDirectXInput::connectTo(int device)
00776 {
00777 if (cCap->device == device)
00778 return VETRET_PARAM_ERR;
00779
00780 if (cCap->device != -1 && cCap->device != device)
00781 disconnect();
00782
00783 if (setDevice(device))
00784 return VETRET_PARAM_ERR;
00785
00786 if (initCaptureGraphBuilder(cCap))
00787 {
00788 SafeRelease(cCap->grabber_filter);
00789 SafeRelease(cCap->filter_builder);
00790 SafeRelease(cCap->capture_graph_builder);
00791 SafeRelease(cCap->null_filter);
00792 free(cCap);
00793 return VETRET_INTERNAL_ERR;
00794 }
00795
00796 cCap->capture_filter = vetGetDevice(device);
00797 if (!cCap->capture_filter)
00798 return VETRET_INTERNAL_ERR;
00799
00800 cCap->filter_builder->AddFilter(cCap->capture_filter, L"VETLibCaptureSource");
00801
00802 vetCheckVideoPort(cCap);
00803
00804
00805
00806
00807 if (vetConnectFilters(cCap->filter_builder, cCap->capture_filter, cCap->grabber_filter, 0))
00808 {
00809 cCap->filter_builder->RemoveFilter(cCap->capture_filter);
00810
00811 SafeRelease(cCap->capture_filter);
00812 SafeRelease(cCap->video_prop);
00813 SafeRelease(cCap->camera_prop);
00814 SafeRelease(cCap->videoctrl_prop);
00815
00816 cCap->live = 0;
00817 cCap->device = -1;
00818
00819 return VETRET_INTERNAL_ERR;
00820 }
00821
00822 vetConnectFilters(cCap->filter_builder, cCap->grabber_filter, cCap->null_filter, 1);
00823
00824 vetUpdateFormatList(cCap);
00825
00826 getImageSize(&width, &height);
00827 cCap->sample_callback->SetImageSize(width, height);
00828
00829 cCap->sample_grabber->SetCallback(cCap->sample_callback, 0);
00830
00831
00832
00833
00834
00835
00836 return VETRET_OK;
00837 }
00838
00844 VETRESULT vetDirectXInput::disconnect()
00845 {
00846 if (cCap->device == -1)
00847 return VETRET_ILLEGAL_USE;
00848
00849 doStopLive();
00850
00851 cCap->sample_grabber->SetCallback(NULL, 0);
00852
00853 if (cCap->overlay_mixer)
00854 doReleaseMixer(cCap);
00855
00856 vetDisconnectFilters(cCap->filter_builder, cCap->grabber_filter, cCap->null_filter);
00857
00858
00859 if (vetDisconnectFilterPin(cCap->filter_builder, cCap->grabber_filter, PINDIR_INPUT))
00860 return VETRET_INTERNAL_ERR;
00861
00862
00863 vetNukeDownstream(cCap->filter_builder, cCap->capture_filter);
00864
00865 cCap->filter_builder->RemoveFilter(cCap->capture_filter);
00866
00867 SafeRelease(cCap->capture_filter);
00868 SafeRelease(cCap->video_prop);
00869 SafeRelease(cCap->camera_prop);
00870 SafeRelease(cCap->videoctrl_prop);
00871
00872 cCap->live = 0;
00873 cCap->device = -1;
00874
00875 height = 0;
00876 width = 0;
00877
00878 return VETRET_OK;
00879 }
00880
00881
00882
00883
00889 bool vetDirectXInput::EoF()
00890 {
00891 if ( getCurrentDevice() == -1 )
00892 return true;
00893
00894 return isLive();
00895 }
00896
00897
00903 VETRESULT vetDirectXInput::reset()
00904 {
00905 return disconnect();
00906
00907 }
00908
00909
00912
00913 VETRESULT vetDirectXInput::openPropertyPage(void* ghwndApp)
00914 {
00915
00916
00917 CAUUID cauuid;
00918
00919
00920 HRESULT hr;
00921
00922
00923 hr = cCap->capture_filter->QueryInterface(IID_ISpecifyPropertyPages, (void **)&cCap->pSpec);
00924
00925 if(hr == S_OK)
00926 {
00927 hr = cCap->pSpec->GetPages(&cauuid);
00928
00929 hr = OleCreatePropertyFrame(static_cast<HWND>(ghwndApp), 30, 30, NULL, 1,
00930 (IUnknown **)&cCap->capture_filter, cauuid.cElems,
00931 (GUID *)cauuid.pElems, 0, 0, NULL);
00932
00933 CoTaskMemFree(cauuid.pElems);
00934 cCap->pSpec->Release();
00935 }
00936 else
00937 return VETRET_INTERNAL_ERR;
00938
00939 return VETRET_OK;
00940
00941 }
00942
00943
00944
00953 VETRESULT vetDirectXInput::setDevice(int device)
00954 {
00955 if (device == -1)
00956 return VETRET_PARAM_ERR;
00957
00958 if (cCap->live)
00959 return VETRET_ILLEGAL_USE;
00960
00961 if (device == cCap->device)
00962 return VETRET_OK;
00963
00964 if (deviceCount == 0)
00965 {
00966 enumerateDevices();
00967 if (deviceCount == 0)
00968 return 1;
00969 }
00970
00971 if (device >= deviceCount)
00972 return VETRET_PARAM_ERR;
00973
00974 cCap->device = device;
00975 return VETRET_OK;
00976 }
00977
00984 void vetDirectXInput::getImageSize(int *width, int *height)
00985 {
00986
00988
00989 AM_MEDIA_TYPE mt;
00990 ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
00991 HRESULT hr = cCap->sample_grabber->GetConnectedMediaType(&mt);
00992
00993 if ( SUCCEEDED(hr) &&
00994 (mt.majortype == MEDIATYPE_Video) &&
00995 (mt.formattype == FORMAT_VideoInfo) &&
00996 (mt.cbFormat >= sizeof (VIDEOINFOHEADER)) &&
00997 (mt.pbFormat != NULL))
00998 {
00999 VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)mt.pbFormat;
01000 *width = pVih->bmiHeader.biWidth;
01001 *height = abs(pVih->bmiHeader.biHeight);
01002 CoTaskMemFree((PVOID)mt.pbFormat);
01003 }
01004 else
01005 {
01006 *width = 0;
01007 *height = 0;
01008 }
01009 }
01010
01011
01017 VETRESULT vetDirectXInput::setImageSize(int width, int height)
01018 {
01019
01020
01021 int state = cCap->live;
01022
01023 doStopLive();
01024
01025
01026 disconnect();
01027
01028 IIPDVDec* pDV = vetGetDVDecoder(cCap);
01029 if (pDV)
01030 {
01031 int size = 0;
01032
01033 switch(width)
01034 {
01035 case 720:
01036 size = DVRESOLUTION_FULL;
01037 break;
01038 case 360:
01039 size = DVRESOLUTION_HALF;
01040 break;
01041 case 180:
01042 size = DVRESOLUTION_QUARTER;
01043 break;
01044 case 88:
01045 size = DVRESOLUTION_DC;
01046 break;
01047 }
01048
01049 if (!size)
01050 return 0;
01051
01052 int ret = SUCCEEDED(pDV->put_IPDisplay(size));
01053 if (ret)
01054 cCap->sample_callback->SetImageSize(width, height);
01055
01056 return ret;
01057 }
01058
01059 IAMStreamConfig *pSC = vetGetStreamConfig(cCap);
01060 if (!pSC)
01061 return VETRET_INTERNAL_ERR;
01062
01063 AM_MEDIA_TYPE *pmt;
01064 HRESULT hr = pSC->GetFormat(&pmt);
01065 if (FAILED(hr))
01066 return VETRET_INTERNAL_ERR;
01067
01068 VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)pmt->pbFormat;
01069 BITMAPINFOHEADER* bih = &vih->bmiHeader;
01070
01071
01072 int data_size = height * ((width * bih->biBitCount + 31) / 32) * 4;
01073
01074 bih->biSize = sizeof(BITMAPINFOHEADER);
01075 bih->biHeight = height;
01076 bih->biWidth = width;
01077 bih->biSizeImage = data_size;
01078
01079 int fps = 30;
01080 vih->dwBitRate = fps * data_size;
01081 vih->AvgTimePerFrame = 10000000 / fps;
01082
01083 pmt->cbFormat = sizeof(VIDEOINFOHEADER);
01084 pmt->lSampleSize = data_size;
01085
01086 hr = pSC->SetFormat(pmt);
01087 pSC->Release();
01088
01089 vetDeleteMediaType(pmt);
01090
01091 int ret = SUCCEEDED(hr);
01092
01093 if (ret)
01094 {
01095 cCap->sample_callback->SetImageSize(width, height);
01096
01097 if (state)
01098 if (connect() || doStartLive())
01099 return VETRET_INTERNAL_ERR;
01100 else
01101 return VETRET_OK;
01102
01103 return VETRET_OK;
01104 }
01105 else
01106 return VETRET_INTERNAL_ERR;
01107 }
01108
01109
01121 int vetDirectXInput::getFormat(int format, int *width, int *height, char* desc)
01122 {
01123
01124
01125
01126
01127 if (format >= cCap->format_count)
01128 return VETRET_PARAM_ERR;
01129
01130 IAMStreamConfig *pSC = vetGetStreamConfig(cCap);
01131 if (!pSC)
01132 return VETRET_INTERNAL_ERR;
01133
01134 VIDEO_STREAM_CONFIG_CAPS scc;
01135 AM_MEDIA_TYPE *pmt;
01136 if (SUCCEEDED(pSC->GetStreamCaps(cCap->format_map[format], &pmt, (BYTE*)&scc)))
01137 {
01138 *width = scc.InputSize.cx;
01139 *height = scc.InputSize.cy;
01140 vetGetFormatName(pmt->subtype, desc);
01141
01142 pSC->Release();
01143 vetDeleteMediaType(pmt);
01144 return VETRET_OK;
01145 }
01146
01147 pSC->Release();
01148 return VETRET_INTERNAL_ERR;
01149 }
01150
01159 VETRESULT vetDirectXInput::setFormat(int format)
01160 {
01161
01162
01163
01164 if (format == -1)
01165 return VETRET_PARAM_ERR;
01166
01167 if (format >= cCap->format_count)
01168 return VETRET_PARAM_ERR;
01169
01170 doStopLive();
01171
01172
01173 disconnect();
01174
01175 IAMStreamConfig *pSC = vetGetStreamConfig(cCap);
01176 if (!pSC)
01177 return VETRET_INTERNAL_ERR;
01178
01179 VIDEO_STREAM_CONFIG_CAPS scc;
01180 AM_MEDIA_TYPE *pmt;
01181 if (FAILED(pSC->GetStreamCaps(cCap->format_map[format], &pmt, (BYTE*)&scc)))
01182 {
01183 pSC->Release();
01184 return VETRET_INTERNAL_ERR;
01185 }
01186
01187 pSC->SetFormat(pmt);
01188 pSC->Release();
01189
01190 cCap->sample_callback->SetImageSize(scc.InputSize.cx, scc.InputSize.cy);
01191
01192 vetDeleteMediaType(pmt);
01193
01194 cCap->format_current = format;
01195
01196
01197
01198 return VETRET_OK;
01199 }
01200
01201
01202
01203
01206
01212 bool vetDirectXInput::isLive()
01213 {
01214 if ( cCap->live == 0)
01215 return false;
01216
01217 return true;
01218 }
01219
01226 int vetDirectXInput::getCurrentDevice()
01227 {
01228 return cCap->device;
01229 }
01230
01236 int vetDirectXInput::getFormatCount()
01237 {
01238 return cCap->format_count;
01239 }
01240
01246 int vetDirectXInput::getFormat()
01247 {
01248 return cCap->format_current;
01249 }
01250
01251
01254
01261 VETRESULT vetDirectXInput::doStartLive()
01262 {
01263 if (cCap->live)
01264 return VETRET_ILLEGAL_USE;
01265
01266 HRESULT hr = cCap->media_control->Run();
01267
01268 if (FAILED(hr))
01269 {
01270 cCap->live = 0;
01271 return VETRET_INTERNAL_ERR;
01272 }
01273
01274 cCap->live = 1;
01275
01276 Sleep(200);
01277
01278 return VETRET_OK;
01279 }
01280
01286 VETRESULT vetDirectXInput::doStopLive()
01287 {
01288 if (!cCap->live)
01289 return VETRET_ILLEGAL_USE;
01290
01291 cCap->media_control->Stop();
01292 cCap->live = 0;
01293
01294
01295 return VETRET_OK;
01296 }
01297
01298
01299
01300
01301
01302
01303
01304
01306
01307
01308
01321 VETRESULT vetDirectXInput::extractTo(vetFrameYUV420& img)
01322 {
01323
01324 INFO("VETRESULT vetDirectXInput::extractTo(vetFrameYUV420& img) [pushing data]")
01325
01326 return VETRET_NOT_IMPLEMENTED;
01327 }
01328
01329
01342 VETRESULT vetDirectXInput::extractTo(vetFrameRGB24& img)
01343 {
01344
01345 INFO("VETRESULT vetDirectXInput::extractTo(vetFrameRGB24& img) [pushing data]")
01346
01347 if ( &img == NULL )
01348 return VETRET_PARAM_ERR;
01349
01350 if ((unsigned int)width != img.width || (unsigned int)height != img.height)
01351 {
01352 delete [] img.data;
01353 img.data = new PixelRGB24[width*height];
01354 }
01355
01356 img.height = (unsigned int)height;
01357 img.width = (unsigned int)width;
01358
01359
01360 doStopLive();
01361
01362 cCap->sample_grabber->SetOneShot(TRUE);
01363
01364 if (doStartLive())
01365 {
01366 cCap->sample_grabber->SetOneShot(FALSE);
01367 return VETRET_INTERNAL_ERR;
01368 }
01369
01370 return cCap->sample_callback->GetImage((unsigned char*)img.data[0], 0, 0);
01371
01372 }
01373
01374
01375
01388 VETRESULT vetDirectXInput::extractTo(vetFrameT<unsigned char>& img)
01389 {
01390 INFO("VETRESULT vetDirectXInput::extractTo(vetFrameT& img) [pushing data]")
01391
01392 if ( &img == NULL )
01393 return VETRET_PARAM_ERR;
01394
01395
01396 return VETRET_NOT_IMPLEMENTED;
01397 }
01398
01399
01400
01401
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413 VETRESULT vetDirectXInput::vetCheckVideoPort(vetDXCapture* vdx)
01414 {
01415 HRESULT hr;
01416
01417 IPin *pPreviewPin = NULL;
01418 hr = vdx->capture_graph_builder->FindPin(
01419 vdx->capture_filter,
01420 PINDIR_OUTPUT,
01421 &PIN_CATEGORY_PREVIEW,
01422 NULL,
01423 FALSE,
01424 0,
01425 &pPreviewPin
01426 );
01427
01428 if (hr == S_OK)
01429 {
01430 pPreviewPin->Release();
01431 return VETRET_INTERNAL_ERR;
01432 }
01433
01434 IPin *pVideoPortPin = NULL;
01435 hr = vdx->capture_graph_builder->FindPin(
01436 vdx->capture_filter,
01437 PINDIR_OUTPUT,
01438 &PIN_CATEGORY_VIDEOPORT,
01439 NULL,
01440 FALSE,
01441 0,
01442 &pVideoPortPin
01443 );
01444
01445 if (FAILED(hr))
01446 return VETRET_INTERNAL_ERR;
01447
01448
01449 CoCreateInstance(CLSID_OverlayMixer, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void **)&vdx->overlay_mixer);
01450
01451
01452 vdx->filter_builder->AddFilter(vdx->overlay_mixer, L"Overlay Mixer");
01453
01454 IPin *pOverlayPin = NULL;
01455 vdx->capture_graph_builder->FindPin(vdx->overlay_mixer, PINDIR_INPUT, NULL, NULL, TRUE, 0, &pOverlayPin);
01456
01457 vdx->filter_builder->Connect(pVideoPortPin, pOverlayPin);
01458 if (FAILED(hr))
01459 return VETRET_INTERNAL_ERR;
01460
01461 SafeRelease(pVideoPortPin);
01462 SafeRelease(pOverlayPin);
01463
01464 CoCreateInstance(CLSID_VideoRenderer, NULL, CLSCTX_INPROC_SERVER,
01465 IID_IBaseFilter, reinterpret_cast<void**>(&vdx->overlay_renderer));
01466 vdx->filter_builder->AddFilter(vdx->overlay_renderer, L"Overlay Renderer");
01467
01468 vetConnectFilters(vdx->filter_builder, vdx->overlay_mixer, vdx->overlay_renderer, 1);
01469
01470 IVideoWindow* pVideoWindow = NULL;
01471 vdx->overlay_renderer->QueryInterface(IID_IVideoWindow,(void**)&pVideoWindow);
01472 pVideoWindow->put_AutoShow(OAFALSE);
01473 pVideoWindow->Release();
01474
01475 return VETRET_OK;
01476 }
01477
01483 void vetDirectXInput::doReleaseMixer(vetDXCapture* vc)
01484 {
01485 IPin *pOverlayPin = vetGetPin(vc->overlay_mixer, PINDIR_INPUT);
01486 IPin *pVideoPortPin = NULL;
01487 pOverlayPin->ConnectedTo(&pVideoPortPin);
01488 vc->filter_builder->Disconnect(pOverlayPin);
01489 vc->filter_builder->Disconnect(pVideoPortPin);
01490 SafeRelease(pVideoPortPin);
01491 SafeRelease(pOverlayPin);
01492
01493 vetDisconnectFilters(vc->filter_builder, vc->overlay_mixer, vc->overlay_renderer);
01494
01495 vc->filter_builder->RemoveFilter(vc->overlay_renderer);
01496 vc->filter_builder->RemoveFilter(vc->overlay_mixer);
01497 SafeRelease(vc->overlay_renderer);
01498 SafeRelease(vc->overlay_mixer);
01499 }
01500
01501
01502
01503
01504 VETRESULT vetDirectXInput::vetUpdateFormatList(vetDXCapture* vdx)
01505 {
01506 vdx->format_count = 0;
01507 vdx->format_current = -1;
01508
01509 IAMStreamConfig *pSC = vetGetStreamConfig(vdx);
01510 if ( !pSC )
01511 return VETRET_INTERNAL_ERR;
01512
01513 int iCount = 0, iSize = 0;
01514 if ( FAILED(pSC->GetNumberOfCapabilities(&iCount, &iSize)) )
01515 {
01516 pSC->Release();
01517 return VETRET_INTERNAL_ERR;
01518 }
01519
01520 AM_MEDIA_TYPE *curr_pmt;
01521 HRESULT hr = pSC->GetFormat(&curr_pmt);
01522 if ( FAILED(hr) )
01523 {
01524 pSC->Release();
01525 return VETRET_INTERNAL_ERR;
01526 }
01527
01528 for (int iFormat = 0; iFormat < iCount; iFormat++)
01529 {
01530 VIDEO_STREAM_CONFIG_CAPS scc;
01531 AM_MEDIA_TYPE *pmt;
01532 if ( SUCCEEDED(pSC->GetStreamCaps(iFormat, &pmt, (BYTE*)&scc)) )
01533 {
01534 if (scc.guid == FORMAT_VideoInfo)
01535 {
01536 VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)curr_pmt->pbFormat;
01537 BITMAPINFOHEADER* bih = &vih->bmiHeader;
01538 int width = bih->biWidth;
01539 int height = abs(bih->biHeight);
01540
01541 if ( curr_pmt->subtype == pmt->subtype &&
01542 width == scc.InputSize.cx &&
01543 height == scc.InputSize.cy )
01544 {
01545 vdx->format_current = vdx->format_count;
01546 }
01547
01548 vdx->format_map[vdx->format_count] = iFormat;
01549 vdx->format_count++;
01550 }
01551
01552 vetDeleteMediaType(pmt);
01553 }
01554 }
01555
01556 vetDeleteMediaType(curr_pmt);
01557 pSC->Release();
01558
01559 return VETRET_OK;
01560 }
01561
01562
01564
01565
01566
01567
01568
01569 static char* Wide2Char(WCHAR* wstr)
01570 {
01571 if (wstr)
01572 {
01573 int n = wcslen(wstr)+1;
01574 char* str = (char*)malloc(n);
01575 WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, n, NULL, NULL);
01576 return str;
01577 }
01578
01579 return NULL;
01580 }
01581
01582
01589 void vetDirectXInput::enumerateDevices(void)
01590 {
01591
01592 ICreateDevEnum *pDevEnum = NULL;
01593 IEnumMoniker *pEnum = NULL;
01594 deviceCount = 0;
01595
01596 CoInitialize(NULL);
01597
01598
01599 HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
01600 CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
01601 reinterpret_cast<void**>(&pDevEnum));
01602 if (FAILED(hr)) return;
01603
01604
01605 hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, CATEGORY_FLAG);
01606 if (FAILED(hr) || !pEnum)
01607 {
01608 pDevEnum->Release();
01609 return;
01610 }
01611
01612 IMoniker *pMoniker = NULL;
01613 while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
01614 {
01615 IPropertyBag *pPropBag;
01616 hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag));
01617 if (FAILED(hr))
01618 {
01619 pMoniker->Release();
01620 continue;
01621 }
01622
01623
01624 VARIANT varName;
01625 VariantInit(&varName);
01626
01627 hr = pPropBag->Read(L"FriendlyName", &varName, 0);
01628 if (SUCCEEDED(hr))
01629 {
01630 char* str = Wide2Char(varName.bstrVal);
01631 sprintf(deviceDesc[deviceCount], "%d - %s", deviceCount, str);
01632 free(str);
01633 VariantClear(&varName);
01634 deviceCount++;
01635 }
01636
01637 pPropBag->Release();
01638 pMoniker->Release();
01639 }
01640
01641 pEnum->Release();
01642 pDevEnum->Release();
01643 }
01644
01651 const char* vetDirectXInput::getDeviceDescription(int device)
01652 {
01653
01654 if (deviceCount == 0)
01655 {
01656 enumerateDevices();
01657
01658 if (deviceCount == 0)
01659 return NULL;
01660 }
01661
01662 if (device >= deviceCount)
01663 return NULL;
01664
01665 return deviceDesc[device];
01666 }
01667
01668