Étape 4. Définir les propriétés de l’allocateur

[La fonctionnalité associée à cette page, DirectShow, est une fonctionnalité héritée. Il a été remplacé par MediaPlayer, IMFMediaEngine et Audio/Video Capture in Media Foundation. Ces fonctionnalités ont été optimisées pour Windows 10 et Windows 11. Microsoft recommande vivement que le nouveau code utilise MediaPlayer, IMFMediaEngine et Audio/Video Capture dans Media Foundation au lieu de DirectShow, si possible. Microsoft suggère que le code existant qui utilise les API héritées soit réécrit pour utiliser les nouvelles API si possible.]

Il s’agit de l’étape 4 du didacticiel Écriture de filtres de transformation.

Notes

Cette étape n’est pas requise pour les filtres qui dérivent de CTransInPlaceFilter.

 

Une fois que deux broches s’accordent sur un type de média, elles sélectionnent un allocateur pour les propriétés de connexion et de négociation de l’allocateur, telles que la taille de la mémoire tampon et le nombre de mémoires tampons.

Dans la classe CTransformFilter, il existe deux allocateurs, l’un pour la connexion de broche amont et l’autre pour la connexion de broche en aval. Le filtre amont sélectionne l’allocateur amont et choisit également les propriétés de l’allocateur. La broche d’entrée accepte ce que le filtre amont décide. Si vous devez modifier ce comportement, remplacez la méthode CBaseInputPin::NotifyAllocator .

La broche de sortie du filtre de transformation sélectionne l’allocateur en aval. Il permet d'effectuer les opérations suivantes :

  1. Si le filtre en aval peut fournir un allocateur, la broche de sortie utilise celui-ci. Sinon, la broche de sortie crée un nouvel allocateur.
  2. La broche de sortie obtient les exigences d’allocation du filtre en aval (le cas échéant) en appelant IMemInputPin::GetAllocatorRequirements.
  3. La broche de sortie appelle la méthode CTransformFilter::D ecideBufferSize du filtre de transformation, qui est virtuelle pure. Les paramètres de cette méthode sont un pointeur vers l’allocateur et une structure ALLOCATOR_PROPERTIES avec les exigences du filtre en aval. Si le filtre en aval n’a aucune exigence d’allocation, la structure est annulée.
  4. Dans la méthode DecideBufferSize , la classe dérivée définit les propriétés d’allocator en appelant IMemAllocator::SetProperties.

En règle générale, la classe dérivée sélectionne les propriétés de l’allocateur en fonction du format de sortie, des exigences du filtre en aval et des propres exigences du filtre. Essayez de sélectionner des propriétés compatibles avec la demande du filtre en aval. Sinon, le filtre en aval peut rejeter la connexion.

Dans l’exemple suivant, l’encodeur RLE définit des valeurs minimales pour la taille de la mémoire tampon, l’alignement de la mémoire tampon et le nombre de mémoires tampons. Pour le préfixe, elle utilise la valeur demandée par le filtre en aval. Le préfixe est généralement égal à zéro octet, mais certains filtres l’exigent. Par exemple, le filtre AVI Mux utilise le préfixe pour écrire des en-têtes 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;
}

L’allocateur peut ne pas être en mesure de correspondre exactement à votre demande. Par conséquent, la méthode SetProperties retourne le résultat réel dans une structure ALLOCATOR_PROPERTIES distincte (le paramètre Actual , dans l’exemple précédent). Même si SetProperties réussit, vous devez case activée le résultat pour vous assurer qu’ils répondent aux exigences minimales de votre filtre.

Allocateurs personnalisés

Par défaut, toutes les classes de filtre utilisent la classe CMemAllocator pour leurs allocateurs. Cette classe alloue de la mémoire à partir de l’espace d’adressage virtuel du processus client (à l’aide de VirtualAlloc). Si votre filtre doit utiliser un autre type de mémoire, tel que les surfaces DirectDraw, vous pouvez implémenter un allocateur personnalisé. Vous pouvez utiliser la classe CBaseAllocator ou écrire une classe allocator entièrement nouvelle. Si votre filtre a un allocateur personnalisé, remplacez les méthodes suivantes, en fonction de l’épingle qui utilise l’allocateur :

Si l’autre filtre refuse de se connecter à l’aide de votre allocateur personnalisé, votre filtre peut soit échouer à la connexion, soit se connecter à l’allocateur de l’autre filtre. Dans ce dernier cas, vous devrez peut-être définir un indicateur interne indiquant le type d’allocateur. Pour obtenir un exemple de cette approche, consultez Classe CDrawImage.

Suivant : Étape 5. Transformez l’image.

Écriture de filtres DirectShow