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.
Argomenti correlati