Paso 4. Establecer propiedades de asignador

[La característica asociada a esta página, DirectShow, es una característica heredada. Se ha reemplazado por MediaPlayer, IMFMediaEngine y Captura de audio/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 Audio/Video Capture 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 es el paso 4 del tutorial Escritura de filtros de transformación.

Nota

Este paso no es necesario para los filtros que derivan de CTransInPlaceFilter.

 

Después de que dos patillas acepten un tipo de medio, seleccionan un asignador para la conexión y negocian las propiedades del asignador, como el tamaño del búfer y el número de búferes.

En la clase CTransformFilter , hay dos asignadores, uno para la conexión de patilla ascendente y otro para la conexión de patilla de bajada. El filtro ascendente selecciona el asignador ascendente y también elige las propiedades del asignador. El pin de entrada acepta lo que decida el filtro ascendente. Si necesita modificar este comportamiento, invalide el método CBaseInputPin::NotifyAllocator .

El pin de salida del filtro de transformación selecciona el asignador de bajada. Realiza los pasos siguientes:

  1. Si el filtro de bajada puede proporcionar un asignador, el pin de salida lo usa. De lo contrario, el pin de salida crea un nuevo asignador.
  2. El pin de salida obtiene los requisitos del asignador del filtro de bajada (si existe) mediante una llamada a IMemInputPin::GetAllocatorRequirements.
  3. El pin de salida llama al método CTransformFilter::D ecideBufferSize del filtro de transformación, que es virtual puro. Los parámetros de este método son un puntero al asignador y una estructura ALLOCATOR_PROPERTIES con los requisitos del filtro de nivel inferior. Si el filtro de bajada no tiene requisitos de asignador, la estructura se agota.
  4. En el método DecideBufferSize , la clase derivada establece las propiedades del asignador mediante una llamada a IMemAllocator::SetProperties.

Por lo general, la clase derivada seleccionará las propiedades del asignador en función del formato de salida, los requisitos del filtro de bajada y los propios requisitos del filtro. Intente seleccionar las propiedades que son compatibles con la solicitud del filtro de bajada. De lo contrario, el filtro de bajada podría rechazar la conexión.

En el ejemplo siguiente, el codificador RLE establece los valores mínimos para el tamaño del búfer, la alineación del búfer y el recuento de búferes. Para el prefijo, usa cualquier valor que solicite el filtro de bajada. El prefijo suele ser cero bytes, pero algunos filtros lo requieren. Por ejemplo, el filtro Mux avi usa el prefijo para escribir encabezados RIFF.

HRESULT CRleFilter::DecideBufferSize(
    IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProp)
{
    AM_MEDIA_TYPE mt;
    HRESULT hr = m_pOutput->ConnectionMediaType(&mt);
    if (FAILED(hr))
    {
        return hr;
    }

    ASSERT(mt.formattype == FORMAT_VideoInfo);
    BITMAPINFOHEADER *pbmi = HEADER(mt.pbFormat);
    pProp->cbBuffer = DIBSIZE(*pbmi) * 2; 
    if (pProp->cbAlign == 0)
    {
        pProp->cbAlign = 1;
    }
    if (pProp->cBuffers == 0)
    {
        pProp->cBuffers = 1;
    }
    // Release the format block.
    FreeMediaType(mt);

    // Set allocator properties.
    ALLOCATOR_PROPERTIES Actual;
    hr = pAlloc->SetProperties(pProp, &Actual);
    if (FAILED(hr)) 
    {
        return hr;
    }
    // Even when it succeeds, check the actual result.
    if (pProp->cbBuffer > Actual.cbBuffer) 
    {
        return E_FAIL;
    }
    return S_OK;
}

Es posible que el asignador no pueda coincidir exactamente con la solicitud. Por lo tanto, el método SetProperties devuelve el resultado real en una estructura ALLOCATOR_PROPERTIES independiente (el parámetro Actual , en el ejemplo anterior). Incluso cuando SetProperties se realiza correctamente, debe comprobar el resultado para asegurarse de que cumplen los requisitos mínimos del filtro.

Asignadores personalizados

De forma predeterminada, todas las clases de filtro usan la clase CMemAllocator para sus asignadores. Esta clase asigna memoria del espacio de direcciones virtuales del proceso de cliente (mediante VirtualAlloc). Si el filtro necesita usar algún otro tipo de memoria, como las superficies de DirectDraw, puede implementar un asignador personalizado. Puede usar la clase CBaseAllocator o escribir una clase de asignador completamente nueva. Si el filtro tiene un asignador personalizado, invalide los métodos siguientes, en función del pin que use el asignador:

Si el otro filtro se niega a conectarse mediante el asignador personalizado, el filtro puede producir un error en la conexión o, de lo contrario, conectarse con el asignador del otro filtro. En este último caso, es posible que tenga que establecer una marca interna que indique el tipo de asignador. Para obtener un ejemplo de este enfoque, vea CDrawImage (clase).

Siguiente: Paso 5. Transforme la imagen.

Escribir filtros directShow