Compartir a través de


QueryAccept (upstream)

[La característica asociada a esta página, DirectShow, es una característica heredada. Se ha reemplazado por MediaPlayer, IMFMediaEnginey captura de audio y vídeo en Media Foundation. Esas características se han optimizado para Windows 10 y Windows 11. Microsoft recomienda encarecidamente que el nuevo código use MediaPlayer, IMFMediaEngine y captura de audio y vídeo en Media Foundation en lugar de DirectShow, siempre que sea posible. Microsoft sugiere que el código existente que usa las API heredadas se reescriba para usar las nuevas API si es posible.

Este mecanismo permite que un pin de entrada propondrá un cambio de formato en su par ascendente. El filtro de bajada debe adjuntar un tipo de medio al ejemplo que el filtro ascendente obtendrá en su siguiente llamada a IMemAllocator::GetBuffer. Sin embargo, para ello, el filtro de bajada debe proporcionar un asignador personalizado para la conexión. Este asignador debe implementar un método privado que el filtro de bajada pueda usar para establecer el tipo de medio en el ejemplo siguiente.

Se producen los pasos siguientes:

  1. El filtro de bajada comprueba si la conexión de anclaje usa el asignador personalizado del filtro. Si el filtro ascendente posee el asignador, el filtro de bajada no puede cambiar el formato.
  2. El filtro de bajada llama a IPin::QueryAccept en el pin de salida ascendente (vea ilustración, paso A).
  3. Si QueryAccept devuelve S_OK, el filtro de bajada llama al método privado en su asignador para establecer el tipo de medio. Dentro de este método privado, el asignador llama a IMediaSample::SetMediaType en el siguiente ejemplo disponible (B).
  4. El filtro ascendente llama GetBuffer para obtener un nuevo ejemplo (C) y IMediaSample::GetMediaType para obtener el tipo de medio (D).
  5. Cuando el filtro ascendente entrega el ejemplo, debe dejar el tipo de medio adjunto a ese ejemplo. De este modo, el filtro de bajada puede confirmar que el tipo de medio ha cambiado (E).

Si el filtro ascendente acepta el cambio de formato, también debe poder volver al tipo de medio original, como se muestra en el diagrama siguiente.

queryaccept (upstream)

Los principales ejemplos de este tipo de cambio de formato implican los representadores de vídeo directShow.

  • El filtro original Video Renderer puede cambiar entre los tipos RGB e YUV durante el streaming. Cuando el filtro se conecta, requiere un formato RGB que coincida con la configuración de visualización actual. Esto garantiza que puede recurrir a GDI si lo necesita. Una vez que comience el streaming, si DirectDraw está disponible, Video Renderer solicita un cambio de formato a un tipo YUV. Más adelante, podría volver a RGB si pierde la superficie de DirectDraw por cualquier motivo.
  • El filtro más reciente del representador de mezcla de vídeos (VMR) se conectará con cualquier formato compatible con el hardware gráfico, incluidos los tipos YUV. Sin embargo, el hardware gráfico podría cambiar el paso de la superficie de DirectDraw subyacente para optimizar el rendimiento. El filtro VMR usa QueryAccept para notificar el nuevo paso, que se especifica en el miembro biWidth de de la estructura BITMAPINFOHEADER. Los rectángulos de origen y destino de la VIDEOINFOHEADER o VIDEOINFOHEADER2 estructura identifican la región donde se debe descodificar el vídeo.

nota de implementación de

Es poco probable que escriba un filtro que necesite solicitar cambios de formato ascendentes, ya que se trata principalmente de una característica de los representadores de vídeo. Sin embargo, si escribe un filtro de transformación de vídeo o un descodificador de vídeo, el filtro debe responder correctamente a las solicitudes del representador de vídeo.

Un filtro trans-in-place que se encuentra entre el representador de vídeo y el descodificador debe pasar todas las llamadas QueryAccept ascendentes. Almacene la nueva información de formato cuando llegue.

Un filtro de copia y transformación (es decir, un filtro no trans-in-place) debe implementar uno de los siguientes comportamientos:

  • Pase los cambios de formato ascendentes y almacene la nueva información de formato cuando llegue. El filtro debe usar un asignador personalizado para que pueda adjuntar el formato al ejemplo ascendente.
  • Realice la conversión de formato dentro del filtro. Esto es probablemente más fácil que pasar el cambio de formato ascendente. Sin embargo, puede ser menos eficaz que permitir que el filtro del descodificador descodifique en el formato correcto.
  • Como último recurso, simplemente rechaza el cambio de formato. (Para obtener más información, consulte el código fuente del método CTransInPlaceOutputPin::CheckMediaType en la biblioteca de clases base directShow). No obstante, rechazar un cambio de formato puede reducir el rendimiento, ya que impide que el representador de vídeo use el formato más eficaz.

El siguiente pseudocódigo muestra cómo puede implementar un filtro de transformación de copia (derivado de CTransformFilter) que puede cambiar entre los tipos de salida YUV y RGB. En este ejemplo se supone que el filtro realiza la propia conversión, en lugar de pasar el cambio de formato ascendente.

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