QueryAccept (Upstream)

[Das dieser Seite zugeordnete Feature DirectShow ist ein Legacyfeature. Es wurde durch MediaPlayer, IMFMediaEngine und Audio/Video Capture in Media Foundation ersetzt. Diese Features wurden für Windows 10 und Windows 11 optimiert. Microsoft empfiehlt dringend, dass neuer Code nach Möglichkeit MediaPlayer, IMFMediaEngine und Audio/Video Capture in Media Foundation anstelle von DirectShow verwendet. Microsoft schlägt vor, vorhandenen Code, der die Legacy-APIs verwendet, um nach Möglichkeit die neuen APIs zu verwenden.]

Mit diesem Mechanismus kann ein Eingabenadel dem Upstream Peer eine Formatänderung vorschlagen. Der Downstreamfilter muss dem Beispiel einen Medientyp anfügen, den der Upstream-Filter beim nächsten Aufruf von IMemAllocator::GetBuffer abrufen wird. Hierzu muss der Downstreamfilter jedoch einen benutzerdefinierten Zuteilungsgeber für die Verbindung bereitstellen. Dieser Zuteilungsgeber muss eine private Methode implementieren, die der nachgeschaltete Filter verwenden kann, um den Medientyp im nächsten Beispiel festzulegen.

Dabei werden die folgenden Schritte ausgeführt:

  1. Der Downstreamfilter überprüft, ob die Pinverbindung den benutzerdefinierten Zuteilungsgeber des Filters verwendet. Wenn der Upstream-Filter den Zuteilungsgeber besitzt, kann der Nachgeschaltete Filter das Format nicht ändern.
  2. Der Downstreamfilter ruft IPin::QueryAccept am Upstream Ausgabenadel auf (siehe Abbildung, Schritt A).
  3. Wenn QueryAccept S_OK zurückgegeben wird, ruft der Nachgelagerte Filter die private Methode auf dem Zugehörigen auf, um den Medientyp festzulegen. Innerhalb dieser privaten Methode ruft der Zuteilungsgeber IMediaSample::SetMediaType im nächsten verfügbaren Beispiel (B) auf.
  4. Der Upstream Filter ruft GetBuffer auf, um ein neues Beispiel (C) abzurufen, und IMediaSample::GetMediaType, um den Medientyp (D) abzurufen.
  5. Wenn der Upstream-Filter das Beispiel übermittelt, sollte der Medientyp an dieses Beispiel angefügt bleiben. Auf diese Weise kann der Downstreamfilter bestätigen, dass sich der Medientyp geändert hat (E).

Wenn der Upstream-Filter die Formatänderung akzeptiert, muss er auch in der Lage sein, zurück zum ursprünglichen Medientyp zu wechseln, wie im folgenden Diagramm dargestellt.

queryaccept (Upstream)

Die Standard Beispiele für diese Art von Formatänderung sind die DirectShow-Videorenderer.

  • Der ursprüngliche Video Renderer-Filter kann während des Streamings zwischen RGB- und YUV-Typen wechseln. Wenn der Filter eine Verbindung herstellt, ist ein RGB-Format erforderlich, das den aktuellen Anzeigeeinstellungen entspricht. Dies garantiert, dass es bei Bedarf auf GDI zurückgreifen kann. Wenn DirectDraw verfügbar ist, fordert der Video-Renderer nach Beginn des Streamings eine Formatänderung in einen YUV-Typ an. Später kann es wieder zu RGB wechseln, wenn die DirectDraw-Oberfläche aus irgendeinem Grund verloren geht.
  • Der neuere VMR-Filter (Video Mixing Renderer) stellt eine Verbindung mit jedem Format her, das von der Grafikhardware unterstützt wird, einschließlich YUV-Typen. Die Grafikhardware kann jedoch den Schritt der zugrunde liegenden DirectDraw-Oberfläche ändern, um die Leistung zu optimieren. Der VMR-Filter verwendet QueryAccept , um den neuen Stride zu melden, der im biWidth-Member der BITMAPINFOHEADER-Struktur angegeben wird. Die Quell- und Zielrechtecke in der STRUKTUR VIDEOINFOHEADER oder VIDEOINFOHEADER2 identifizieren die Region, in der das Video decodiert werden soll.

Hinweis zur Implementierung

Es ist unwahrscheinlich, dass Sie einen Filter schreiben, der Upstream Formatänderungen anfordern muss, da dies hauptsächlich ein Feature von Videorenderern ist. Wenn Sie jedoch einen Videotransformationsfilter oder einen Videodecoder schreiben, muss Ihr Filter ordnungsgemäß auf Anforderungen des Videorenderers reagieren.

Ein Trans-in-Place-Filter, der sich zwischen dem Videorenderer und dem Decoder befindet, sollte alle QueryAccept Aufrufe Upstream übergeben. Speichern Sie die neuen Formatinformationen, wenn sie eintreffen.

Ein Kopiertransformationsfilter (d. a. ein Nicht-Trans-In-Place-Filter) sollte eines der folgenden Verhaltensweisen implementieren:

  • Übergeben Sie Formatänderungen Upstream, und speichern Sie die neuen Formatinformationen beim Eintreffen. Ihr Filter muss einen benutzerdefinierten Zuteilungsgeber verwenden, damit er das Format an das Upstream Beispiel anfügen kann.
  • Führen Sie die Formatkonvertierung im Filter aus. Dies ist wahrscheinlich einfacher, als die Formatänderung Upstream zu übergeben. Es kann jedoch weniger effizient sein, als den Decoderfilter in das richtige Format decodieren zu lassen.
  • Als letztes Mittel lehnen Sie einfach die Formatänderung ab. (Weitere Informationen finden Sie im Quellcode für die CTransInPlaceOutputPin::CheckMediaType-Methode in der DirectShow-Basisklassenbibliothek.) Das Ablehnen einer Formatänderung kann jedoch die Leistung beeinträchtigen, da der Videorenderer nicht das effizienteste Format verwendet.

Der folgende Pseudocode zeigt, wie Sie einen Kopiertransformationsfilter (abgeleitet von CTransformFilter) implementieren können, der zwischen YUV- und RGB-Ausgabetypen wechseln kann. In diesem Beispiel wird davon ausgegangen, dass der Filter die Konvertierung selbst durchführt, anstatt die Formatänderung Upstream.

HRESULT CMyTransform::CheckInputType(const CMediaType *pmt)
{
    if (pmt is a YUV type that you support) {
        return S_OK;
    }
    else {
        return VFW_E_TYPE_NOT_ACCEPTED;
    }
}

HRESULT CMyTransform::CheckTransform(
    const CMediaType *mtIn, const CMediaType *mtOut)
{
    if (mtOut is a YUV or RGB type that you support)
    {
        if ((mtIn has the same video dimensions as mtOut) &&
            (you support the mtIn-to-mtOut transform))
        {
            return S_OK;
        }
    }
    // otherwise
    return VFW_E_TYPE_NOT_ACCEPTED;
}

// GetMediaType: Return a preferred output type.
HRESULT CMyTransform::GetMediaType(int iPosition, CMediaType *pMediaType)
{
    if (iPosition < 0) {
        return E_INVALIDARG;
    }
    switch (iPosition)
    {
    case 0:
        Copy the input type (YUV) to pMediaType
        return S_OK;
    case 1:
        Construct an RGB type that matches the input type.
        return S_OK;
    default:
        return VFW_S_NO_MORE_ITEMS;
    }
}

// SetMediaType: Override from CTransformFilter. 
HRESULT CMyTransform::SetMediaType(
    PIN_DIRECTION direction, const CMediaType *pmt)
{
    // Capture this information...
    if (direction == PINDIR_OUTPUT)
    {
       m_bYuv = (pmt->subtype == MEDIASUBTYPE_UYVY);
    }
    return S_OK;
}

HRESULT CMyTransform::Transform(
    IMediaSample *pSource, IMediaSample *pDest)
{
    // Look for format changes from downstream.
    CMediaType *pMT = NULL;
    HRESULT hr = pDest->GetMediaType((AM_MEDIA_TYPE**)&pMT);
    if (hr == S_OK)
    {
        hr = m_pOutput->CheckMediaType(pMT);
        if(FAILED(hr))
        {
            DeleteMediaType(pMT);
            return E_FAIL;
        }
        // Notify our own output pin about the new type.
        m_pOutput->SetMediaType(pMT);
        DeleteMediaType(pMT);
    }
    // Process the buffers
    if (m_bYuv) {
        return ProcessFrameYUV(pSource, pDest);
    }
    else {
        return ProcessFrameRGB(pSource, pDest);
    }
}