Как снимать живые кадры камеры в RGB с DirectShow

m осуществляет захват видео в реальном времени через DirectShow для обработки и отображения в реальном времени. (Дополненная реальность приложение).

Я могу получить доступ к пикселям достаточно легко, но, кажется, я могуполучить SampleGrabber для предоставления данных RGB. Устройство (на iSight работает VC ++ Express в VMWare) сообщает только MEDIASUBTYPE_YUY2.

После продолжительного поиска в Google, я все еще могуt выяснить, должен ли DirectShow обеспечивать встроенное преобразование цветового пространства для такого рода вещей. Некоторые сайты сообщают, что нет YUV <->Встроенное преобразование RGB,другие сообщите, что вам просто нужно вызвать SetMediaType на ISampleGrabber с подтипом RGB.

Любой совет с благодарностью, яЯ схожу с ума по этому. Код предоставлен ниже. Обратите внимание, что

Код работает, за исключением того, что он неt предоставить данные RGBI '

Я знаю, что могу реализовать свой собственный фильтр преобразования, но это невозможно, потому что яЯ должен был предвидеть каждый возможный формат устройства, и это относительно небольшой проект

// 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;

Ответы на вопрос(1)

Ваш ответ на вопрос