Frage

Ich implementiere Live -Video -Capture über DirectShow für Live -Verarbeitung und -anzeige. (Augmented Reality App).

Ich kann leicht genug auf die Pixel zugreifen, aber es scheint, dass ich den SampleGrabber nicht dazu bringen kann, RGB -Daten bereitzustellen. Das Gerät (ein ISight - Ausführen von VC ++ Express in VMware) meldet nur MediaSubType_yuy2.

Nach umfangreichem Googeln kann ich immer noch nicht herausfinden, ob DirectShow ein integriertes Farbraumkonvertierung für solche Dinge bieten soll. Einige Websites berichten, dass es keine YUV <--> RGB-Umwandlung eingebaut gibt, Andere Melden Sie, dass Sie SetMediType nur auf Ihrem Isamplegrabber mit einem RGB -Subtyp aufrufen müssen.

Jeder Rat wird sehr geschätzt, ich werde in diesem Fall verrückt. Code unten angegeben. Bitte beachte, dass

  • Der Code funktioniert, außer dass er keine RGB -Daten liefert
  • Ich bin mir bewusst, dass ich meinen eigenen Conversion -Filter implementieren kann, aber dies ist nicht machbar, da ich jedes mögliche Geräteformat vorhersehen müsste, und dies ist ein relativ kleines Projekt

    // 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;
    
War es hilfreich?

Lösung

Der Color Space Converter unterstützt Yuy2 nicht zur RGB -Konvertierung. Es gibt jedoch eine Reihe von Apps und Geräten, die einen Sortierer installieren. Wenn dies ordnungsgemäß registriert ist, verwendet Dshow ihn automatisch. Deshalb berichten einige Leute, dass es einfach funktioniert. (Natürlich bieten einige Geräte RGB an, sodass in diesen Fällen keine Konvertierung erforderlich ist).

Sie können einen frei verfügbaren YUV-Conversion-Filter "Yuvxfm" von frei zugänglich machen YUV -Transformation (unten auf der Seite). Registrieren Sie dies in Ihrem System und es sollte die Erfassung in einem angemessenen RGB- oder YUV -Format ermöglichen.

G

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top