4

라이브 프로세싱 및 디스플레이를 위해 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; 
      
  • 답변

    4

    주식 색 공간 변환이 RGB 변환에 YUY2를 지원하지 않는 상대적으로 작은 프로젝트입니다. 그러나, 일종의 변환기를 설치하는 많은 응용 프로그램과 장치가 있으며, 제대로 등록되어 있으면 dshow가 자동으로이 변환기를 사용합니다. 그래서 일부 사람들은 그것이 효과가 있다고보고합니다. (물론 일부 장치는 RGB를 제공하므로 이러한 경우에는 변환이 필요하지 않습니다.)

    YUV Transform (at the bottom of the page)에서 자유롭게 사용할 수있는 YUV 변환 필터 "yuvxfm"을 다운로드 할 수 있습니다. 시스템에 등록하면 알맞은 RGB 또는 YUV 형식으로 캡처 할 수 있습니다.

    g

    +0

    정보를 보내 주셔서 감사합니다. 장치와 샘플 그래버 사이에 yuvxfm 필터를 추가하여 보았습니다. 그러나, 그것도없이 작동한다면 나는 또한 발견했다. 나는 yuvxfm 등록을 취소하고 장치에서 rgb 샘플 그래버로 직접 이동하려고했습니다. 나는 왜 그것이 전에 작동하지 않았는지 모르겠다. XP SP3의 거의 새로운 설치를 실행 중입니다. 또한 작동하는 Windows 7에서도 사용해 보았습니다. YUY2에서 RGB 로의 변환은 어디에서 발생합니까? 이것에 의지 할 수 있을까요? – Simplex

    +0

    예. AviDecompressor는 YUY2 FourCC를 지원합니다. 제공되는 필터 목록은 http://msdn.microsoft.com/en-us/library/dd375464%28v=VS.85%29.aspx를 참조하십시오. – Christopher

    +0

    AviDecompressor는 Windows 용 비디오 코덱의 래퍼입니다. YUY2 변환을 수행하는 VfW 코덱이 설치되어있을 가능성이 있지만 시스템에 따라 다릅니다. 일부 시스템에서는 YUY2 지원없이 Avi Decompressor 래퍼 필터가있을 수 있습니다. –

    관련 문제