Freigeben über


QueryAccept (Upstream)

[Das dieser Seite zugeordnete Feature DirectShow-ist ein Legacyfeature. Es wurde von MediaPlayer, IMFMediaEngineund Audio/Video Capture in Media Foundationersetzt. Diese Features wurden für Windows 10 und Windows 11 optimiert. Microsoft empfiehlt dringend, dass neuer Code MediaPlayer-, IMFMediaEngine und Audio-/Videoaufnahme in Media Foundation anstelle von DirectShow-verwendet, wenn möglich. Microsoft schlägt vor, dass vorhandener Code, der die Legacy-APIs verwendet, um die neuen APIs zu verwenden, falls möglich umgeschrieben werden.]

Mit diesem Mechanismus kann ein Eingabe-Pin eine Formatänderung an seinem upstream-Peer vorschlagen. Der nachgeschaltete Filter muss einen Medientyp an das Beispiel anfügen, das der Upstreamfilter im nächsten Aufruf von IMemAllocator::GetBufferabruft. Um dies zu tun, muss der Downstreamfilter jedoch einen benutzerdefinierten Allocator für die Verbindung bereitstellen. Dieser Allocator muss eine private Methode implementieren, mit der der nachgeschaltete Filter den Medientyp im nächsten Beispiel festlegen kann.

Die folgenden Schritte treten auf:

  1. Der nachgeschaltete Filter überprüft, ob die Pinverbindung den benutzerdefinierten Ocator des Filters verwendet. Wenn der Upstreamfilter den Allocator besitzt, kann der nachgeschaltete Filter das Format nicht ändern.
  2. Der downstream-Filter ruft IPin::QueryAccept auf dem Upstream-Ausgabeheft auf (siehe Abbildung, Schritt A).
  3. Wenn QueryAccept S_OK zurückgibt, ruft der nachgeschaltete Filter die private Methode für den Allocator auf, um den Medientyp festzulegen. Innerhalb dieser privaten Methode ruft der Allocator IMediaSample::SetMediaType im nächsten verfügbaren Beispiel (B) auf.
  4. Der Upstreamfilter ruft GetBuffer auf, um ein neues Beispiel (C) abzurufen und IMediaSample::GetMediaType, um den Medientyp (D) abzurufen.
  5. Wenn der Upstreamfilter das Beispiel liefert, sollte er den medientyp an dieses Beispiel angefügt lassen. Auf diese Weise kann der nachgeschaltete Filter bestätigen, dass sich der Medientyp geändert hat (E).

Wenn der Upstreamfilter die Formatänderung akzeptiert, muss er auch wieder zum ursprünglichen Medientyp wechseln können, wie im folgenden Diagramm dargestellt.

queryaccept (upstream)

Die Hauptbeispiele dieser Art von Formatänderung umfassen die DirectShow-Videorenderer.

  • Der ursprüngliche Videorenderer 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 sie bei Bedarf auf GDI zurückgreifen kann. Wenn DirectDraw verfügbar ist, fordert der Videorenderer nach Beginn des Streamings eine Formatänderung an einen YUV-Typ an. Später wechselt er möglicherweise wieder zu RGB, 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 die Stride der zugrunde liegenden DirectDraw-Oberfläche ändern, um die Leistung zu optimieren. Der VMR-Filter verwendet QueryAccept, um die neue Stride zu melden, die im biWidth- Member der BITMAPINFOHEADER- Struktur angegeben ist. Die Quell- und Zielrechtecke im VIDEOINFOHEADER oder VIDEOINFOHEADER2 Struktur identifizieren den Bereich, in dem das Video decodiert werden soll.

Implementierungshinweis

Es ist unwahrscheinlich, dass Sie einen Filter schreiben, der vorgelagerte Formatänderungen anfordern muss, da dies hauptsächlich ein Feature von Videorenderern ist. Wenn Sie jedoch einen Videotransformationsfilter oder einen Videodecoder schreiben, muss der 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 vorgelagert übergeben. Speichern Sie die neuen Formatinformationen, wenn sie eintreffen.

Ein Kopiertransformationsfilter (d. h. ein Nicht-In-Situ-Filter) sollte eins der folgenden Verhaltensweisen implementieren:

  • Übergeben Sie Die Formatänderungen vorgelagert, und speichern Sie die neuen Formatinformationen, wenn sie eintreffen. Ihr Filter muss einen benutzerdefinierten Allocator verwenden, damit es das Format an das Upstreambeispiel anfügen kann.
  • Führen Sie die Formatkonvertierung innerhalb des Filters aus. Dies ist wahrscheinlich einfacher als das Übergeben der Formatänderung vorgelagert. Es kann jedoch weniger effizient sein, als die Decodierung des Decoderfilters in das richtige Format zuzulassen.
  • 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 verringern, da sie verhindert, dass der Videorenderer 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 vorgelagert zu übergeben.

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);
    }
}