Share via


Passaggio 5. Trasformare l'immagine

[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stata sostituita da MediaPlayer, FMMediaEngine e Audio/Video Capture in Media Foundation. Queste funzionalità sono state ottimizzate per Windows 10 e Windows 11. Microsoft consiglia vivamente che il nuovo codice usi MediaPlayer, FMMediaEngine e Audio/Video Capture in Media Foundation anziché DirectShow, quando possibile. Microsoft suggerisce che il codice esistente che usa le API legacy venga riscritto per usare le nuove API, se possibile.

Questo è il passaggio 5 dell'esercitazione Scrittura di filtri di trasformazione.

Il filtro upstream fornisce esempi multimediali al filtro di trasformazione chiamando il metodo IMemInputPin::Receive nel pin di input del filtro di trasformazione. Per elaborare i dati, il filtro di trasformazione chiama il metodo Transform, che è virtuale puro. Le classi CTransformFilter e CTransInPlaceFilter usano due versioni diverse di questo metodo:

  • CTransformFilter::Transform accetta un puntatore all'esempio di input e un puntatore all'esempio di output. Prima che il filtro chiami il metodo, copia le proprietà di esempio dall'esempio di input all'esempio di output, inclusi i timestamp.
  • CTransInPlaceFilter::Transform accetta un puntatore all'esempio di input. Il filtro modifica i dati sul posto.

Se il metodo Transform restituisce S_OK, il filtro fornisce l'esempio downstream. Per ignorare un frame, restituire S_FALSE. Se si verifica un errore di streaming, restituire un codice di errore.

Nell'esempio seguente viene illustrato come il codificatore RLE potrebbe implementare questo metodo. La propria implementazione potrebbe variare notevolmente, a seconda di ciò che il filtro fa.

HRESULT CRleFilter::Transform(IMediaSample *pSource, IMediaSample *pDest)
{
    // Get pointers to the underlying buffers.
    BYTE *pBufferIn, *pBufferOut;
    hr = pSource->GetPointer(&pBufferIn);
    if (FAILED(hr))
    {
        return hr;
    }
    hr = pDest->GetPointer(&pBufferOut);
    if (FAILED(hr))
    {
        return hr;
    }
    // Process the data.
    DWORD cbDest = EncodeFrame(pBufferIn, pBufferOut);
    KASSERT((long)cbDest <= pDest->GetSize());

    pDest->SetActualDataLength(cbDest);
    pDest->SetSyncPoint(TRUE);
    return S_OK;
}

In questo esempio si presuppone che EncodeFrame sia un metodo privato che implementa la codifica RLE. L'algoritmo di codifica stesso non è descritto qui; per informazioni dettagliate, vedere l'argomento "Compressione bitmap" nella documentazione di Platform SDK.

Prima di tutto, l'esempio chiama IMediaSample::GetPointer per recuperare gli indirizzi dei buffer sottostanti. Queste vengono passate al metodo EncoderFrame privato. Chiama quindi IMediaSample::SetActualDataLength per specificare la lunghezza dei dati codificati. Il filtro downstream richiede queste informazioni in modo che possa gestire correttamente il buffer. Infine, il metodo chiama IMediaSample::SetSyncPoint per impostare il flag del fotogramma chiave su TRUE. La codifica della lunghezza di esecuzione non usa fotogrammi differenziali, quindi ogni frame è un frame chiave. Per i fotogrammi differenziali, impostare il valore su FALSE.

Altri problemi da considerare includono:

  • Timestamp. La classe CTransformFilter restituisce il timestamp dell'esempio di output prima di chiamare il metodo Transform . Copia i valori del timestamp dall'esempio di input, senza modificarli. Se il filtro deve modificare i timestamp, chiamare IMediaSample::SetTime nell'esempio di output.

  • Modifica del formato. Il filtro upstream può modificare i formati di flusso medio associando un tipo di supporto all'esempio. Prima di farlo, chiama IPin::QueryAccept nel pin di input del filtro. Nella classe CTransformFilter questo risultato viene eseguita una chiamata a CheckInputType seguita da CheckTransform. Il filtro downstream può anche modificare i tipi di supporti usando lo stesso meccanismo. Nel proprio filtro sono disponibili due elementi per watch:

    • Assicurarsi che QueryAccept non restituisca false accettazioni.
    • Se il filtro accetta modifiche di formato, verificare che all'interno del metodo Transform chiami IMediaSample::GetMediaType. Se il metodo restituisce S_OK, il filtro deve rispondere alla modifica del formato.

    Per altre informazioni, vedere Modifiche al formato dinamico.

  • Discussioni. In CTransformFilter e CTransInPlaceFilter il filtro di trasformazione fornisce esempi di output sincroni all'interno del metodo Receive. Il filtro non crea thread di lavoro per elaborare i dati. In genere, non esiste motivo per un filtro di trasformazione per creare thread di lavoro.

Avanti: Passaggio 6. Aggiungere il supporto per COM.

Scrittura di filtri DirectShow