라이브 프로세싱 및 디스플레이를 위해 DirectShow를 통해 라이브 비디오 캡처를 구현하고 있습니다. (증강 현실 앱).DirectShow로 RGB의 라이브 카메라 프레임을 캡쳐하는 방법
픽셀에 쉽게 액세스 할 수 있지만 RGB 데이터를 제공하기 위해 SampleGrabber를 가져올 수없는 것 같습니다. 장치 (iSight - VMWare의 VC++ Express 실행)는 MEDIASUBTYPE_YUY2 만보고합니다.
광범위하게 인터넷을 검색 한 결과 DirectShow가 내장 된 색상 공간 변환 기능을 제공하는지 여부를 파악할 수 없습니다. 일부 사이트에서는 YBY < -> RGB 변환이 내장되어 있지 않으며 others 보고서는 RGB 하위 유형이있는 ISampleGrabber에서 SetMediaType을 호출해야한다는 보고서입니다.
모든 조언을 크게 주시면 감사하겠습니다. 코드는 아래에 제공됩니다. 코드는이 RGB 데이터
나는 내 자신의 변환 필터를 구현할 수 있다는 것을 알고 있어요를 제공하지 않는다는 점을 제외 작동
- 있습니다,하지만 난해야 할 것 때문은 가능하지 않습니다하세요 가능한 모든 장치 형식을 예상하고,이
// Playback IGraphBuilder *pGraphBuilder = NULL; ICaptureGraphBuilder2 *pCaptureGraphBuilder2 = NULL; IMediaControl *pMediaControl = NULL; IBaseFilter *pDeviceFilter = NULL; IAMStreamConfig *pStreamConfig = NULL; BYTE *videoCaps = NULL; AM_MEDIA_TYPE **mediaTypeArray = NULL; // Device selection ICreateDevEnum *pCreateDevEnum = NULL; IEnumMoniker *pEnumMoniker = NULL; IMoniker *pMoniker = NULL; ULONG nFetched = 0; HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); // Create CreateDevEnum to list device hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (PVOID *)&pCreateDevEnum); if (FAILED(hr)) goto ReleaseDataAndFail; // Create EnumMoniker to list devices hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumMoniker, 0); if (FAILED(hr)) goto ReleaseDataAndFail; pEnumMoniker->Reset(); // Find desired device while (pEnumMoniker->Next(1, &pMoniker, &nFetched) == S_OK) { IPropertyBag *pPropertyBag; TCHAR devname[256]; // bind to IPropertyBag hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropertyBag); if (FAILED(hr)) { pMoniker->Release(); continue; } VARIANT varName; VariantInit(&varName); HRESULT hr = pPropertyBag->Read(L"DevicePath", &varName, 0); if (FAILED(hr)) { pMoniker->Release(); pPropertyBag->Release(); continue; } char devicePath[DeviceInfo::STRING_LENGTH_MAX] = ""; wcstombs(devicePath, varName.bstrVal, DeviceInfo::STRING_LENGTH_MAX); if (strcmp(devicePath, deviceId) == 0) { // Bind Moniker to Filter pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pDeviceFilter); break; } pMoniker->Release(); pPropertyBag->Release(); } if (pDeviceFilter == NULL) goto ReleaseDataAndFail; // Create sample grabber IBaseFilter *pGrabberF = NULL; hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pGrabberF); if (FAILED(hr)) goto ReleaseDataAndFail; hr = pGrabberF->QueryInterface(IID_ISampleGrabber, (void**)&pGrabber); if (FAILED(hr)) goto ReleaseDataAndFail; // Create FilterGraph hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (LPVOID *)&pGraphBuilder); if (FAILED(hr)) goto ReleaseDataAndFail; // create CaptureGraphBuilder2 hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, IID_ICaptureGraphBuilder2, (LPVOID *)&pCaptureGraphBuilder2); if (FAILED(hr)) goto ReleaseDataAndFail; // set FilterGraph hr = pCaptureGraphBuilder2->SetFiltergraph(pGraphBuilder); if (FAILED(hr)) goto ReleaseDataAndFail; // get MediaControl interface hr = pGraphBuilder->QueryInterface(IID_IMediaControl, (LPVOID *)&pMediaControl); if (FAILED(hr)) goto ReleaseDataAndFail; // Add filters hr = pGraphBuilder->AddFilter(pDeviceFilter, L"Device Filter"); if (FAILED(hr)) goto ReleaseDataAndFail; hr = pGraphBuilder->AddFilter(pGrabberF, L"Sample Grabber"); if (FAILED(hr)) goto ReleaseDataAndFail; // Set sampe grabber options AM_MEDIA_TYPE mt; ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE)); mt.majortype = MEDIATYPE_Video; mt.subtype = MEDIASUBTYPE_RGB32; hr = pGrabber->SetMediaType(&mt); if (FAILED(hr)) goto ReleaseDataAndFail; hr = pGrabber->SetOneShot(FALSE); if (FAILED(hr)) goto ReleaseDataAndFail; hr = pGrabber->SetBufferSamples(TRUE); if (FAILED(hr)) goto ReleaseDataAndFail; // Get stream config interface hr = pCaptureGraphBuilder2->FindInterface(NULL, &MEDIATYPE_Video, pDeviceFilter, IID_IAMStreamConfig, (void **)&pStreamConfig); if (FAILED(hr)) goto ReleaseDataAndFail; int streamCapsCount = 0, capsSize, bestFit = -1, bestFitPixelDiff = 1000000000, desiredPixelCount = _width * _height, bestFitWidth = 0, bestFitHeight = 0; float desiredAspectRatio = (float)_width/(float)_height; hr = pStreamConfig->GetNumberOfCapabilities(&streamCapsCount, &capsSize); if (FAILED(hr)) goto ReleaseDataAndFail; videoCaps = (BYTE *)malloc(capsSize * streamCapsCount); mediaTypeArray = (AM_MEDIA_TYPE **)malloc(sizeof(AM_MEDIA_TYPE *) * streamCapsCount); for (int i = 0; i < streamCapsCount; i++) { hr = pStreamConfig->GetStreamCaps(i, &mediaTypeArray[i], videoCaps + capsSize * i); if (FAILED(hr)) continue; VIDEO_STREAM_CONFIG_CAPS *currentVideoCaps = (VIDEO_STREAM_CONFIG_CAPS *)(videoCaps + capsSize * i); int closestWidth = MAX(currentVideoCaps->MinOutputSize.cx, MIN(currentVideoCaps->MaxOutputSize.cx, width)); int closestHeight = MAX(currentVideoCaps->MinOutputSize.cy, MIN(currentVideoCaps->MaxOutputSize.cy, height)); int pixelDiff = ABS(desiredPixelCount - closestWidth * closestHeight); if (pixelDiff < bestFitPixelDiff && ABS(desiredAspectRatio - (float)closestWidth/(float)closestHeight) < 0.1f) { bestFit = i; bestFitPixelDiff = pixelDiff; bestFitWidth = closestWidth; bestFitHeight = closestHeight; } } if (bestFit == -1) goto ReleaseDataAndFail; AM_MEDIA_TYPE *mediaType; hr = pStreamConfig->GetFormat(&mediaType); if (FAILED(hr)) goto ReleaseDataAndFail; VIDEOINFOHEADER *videoInfoHeader = (VIDEOINFOHEADER *)mediaType->pbFormat; videoInfoHeader->bmiHeader.biWidth = bestFitWidth; videoInfoHeader->bmiHeader.biHeight = bestFitHeight; //mediaType->subtype = MEDIASUBTYPE_RGB32; hr = pStreamConfig->SetFormat(mediaType); if (FAILED(hr)) goto ReleaseDataAndFail; pStreamConfig->Release(); pStreamConfig = NULL; free(videoCaps); videoCaps = NULL; free(mediaTypeArray); mediaTypeArray = NULL; // Connect pins IPin *pDeviceOut = NULL, *pGrabberIn = NULL; if (FindPin(pDeviceFilter, PINDIR_OUTPUT, 0, &pDeviceOut) && FindPin(pGrabberF, PINDIR_INPUT, 0, &pGrabberIn)) { hr = pGraphBuilder->Connect(pDeviceOut, pGrabberIn); if (FAILED(hr)) goto ReleaseDataAndFail; } else { goto ReleaseDataAndFail; } // start playing hr = pMediaControl->Run(); if (FAILED(hr)) goto ReleaseDataAndFail; hr = pGrabber->GetConnectedMediaType(&mt); // Set dimensions width = bestFitWidth; height = bestFitHeight; _width = bestFitWidth; _height = bestFitHeight; // Allocate pixel buffer pPixelBuffer = (unsigned *)malloc(width * height * 4); // Release objects pGraphBuilder->Release(); pGraphBuilder = NULL; pEnumMoniker->Release(); pEnumMoniker = NULL; pCreateDevEnum->Release(); pCreateDevEnum = NULL; return true;
정보를 보내 주셔서 감사합니다. 장치와 샘플 그래버 사이에 yuvxfm 필터를 추가하여 보았습니다. 그러나, 그것도없이 작동한다면 나는 또한 발견했다. 나는 yuvxfm 등록을 취소하고 장치에서 rgb 샘플 그래버로 직접 이동하려고했습니다. 나는 왜 그것이 전에 작동하지 않았는지 모르겠다. XP SP3의 거의 새로운 설치를 실행 중입니다. 또한 작동하는 Windows 7에서도 사용해 보았습니다. YUY2에서 RGB 로의 변환은 어디에서 발생합니까? 이것에 의지 할 수 있을까요? – Simplex
예. AviDecompressor는 YUY2 FourCC를 지원합니다. 제공되는 필터 목록은 http://msdn.microsoft.com/en-us/library/dd375464%28v=VS.85%29.aspx를 참조하십시오. – Christopher
AviDecompressor는 Windows 용 비디오 코덱의 래퍼입니다. YUY2 변환을 수행하는 VfW 코덱이 설치되어있을 가능성이 있지만 시스템에 따라 다릅니다. 일부 시스템에서는 YUY2 지원없이 Avi Decompressor 래퍼 필터가있을 수 있습니다. –