Condividi tramite


Modello di elaborazione MFT di base

In questo argomento viene descritto come un client usa una trasformazione Media Foundation (MFT) per elaborare i dati. Il client è qualsiasi elemento che chiama direttamente i metodi in MFT. Potrebbe trattarsi dell'applicazione o della pipeline di Media Foundation.

Leggi questo argomento se sei:

  • Scrittura di un'applicazione che effettua chiamate dirette a uno o più MFP.
  • Stai scrivendo un MFT personalizzato e vuoi capire il comportamento previsto di un MFT.

In questo argomento viene descritto un modello di elaborazione sincrono. In questo modello tutti i metodi di elaborazione dati vengono bloccati fino al completamento. Le MFP possono supportare anche un modello di asincrono, descritto nell'argomento MFP asincrone.

Modello di elaborazione di base

Creare il MFT

Esistono diversi modi per creare un MFT:

  • Chiamare la funzione MFTEnum.
  • Chiamare la funzione MFTEnumEx.
  • Se si conosce già il CLSID di MFT, è sufficiente chiamare CoCreateInstance.

Alcune MFP potrebbero fornire altre opzioni, ad esempio una funzione di creazione specializzata.

Ottenere gli identificatori di flusso

Un MFT dispone di uno o più flussi . I flussi di input ricevono dati di input e i flussi di output generano dati di output. I flussi non sono rappresentati come oggetti distinti. I vari metodi MFT accettano invece gli identificatori di flusso come parametri.

Alcune MFP consentono al client di aggiungere o rimuovere flussi di input. Durante lo streaming, un MFT può aggiungere o rimuovere flussi di output. Il client non può aggiungere o rimuovere flussi di output.

  1. (Facoltativo. Chiamare IMFTransform::GetStreamLimits per ottenere il numero minimo e massimo di flussi supportati da MFT. Se il valore minimo e massimo sono uguali, MFT ha un numero fisso di flussi.
  2. Chiamare IMFTransform::GetStreamCount per ottenere il numero iniziale di flussi.
  3. Chiamare IMFTransform::GetStreamIDs per ottenere gli identificatori del flusso. Se questo metodo restituisce E_NOTIMPL, significa che MFT ha un numero fisso di flussi e gli identificatori di flusso sono consecutivi a partire da zero.
  4. (Facoltativo. Se MFT non dispone di un numero fisso di flussi, chiamare IMFTransform::AddInputStreams per aggiungere altri flussi di input o IMFTransform::D eleteInputStream per rimuovere i flussi di input. Non è possibile aggiungere o rimuovere flussi di output.

Impostare tipi di media

Prima che un MFT possa elaborare i dati, il client deve impostare un tipo di supporto per ognuno dei flussi di MFT. Un MFT potrebbe richiedere che il client imposti i tipi di input prima di impostare i tipi di output o che richieda prima l'ordine opposto (tipi di output). Alcuni MFT non hanno un requisito per l'ordine.

Un MFT può fornire un elenco di tipi di supporto preferiti per un flusso. Inoltre, le funzioni a più fattori possono indicare i formati generali supportati aggiungendo queste informazioni al Registro di sistema.

Per impostare i tipi di supporti, eseguire le operazioni seguenti:

  1. (Facoltativo. Per ogni flusso di input, chiamare IMFTransform::GetInputAvailableType per ottenere l'elenco dei tipi preferiti per tale flusso.
    • Se questo metodo restituisce MF_E_TRANSFORM_TYPE_NOT_SET, è necessario impostare prima i tipi di output; andare al passaggio 3.
    • Se il metodo restituisce E_NOTIMPL, MFT non dispone di un elenco di tipi di input preferiti; andare al passaggio 2.
  2. Per ogni flusso di input, chiamare IMFTransform::SetInputType per impostare il tipo di input. È possibile usare un tipo di supporto del passaggio 1 o un tipo che descrive i dati di input. Se un flusso restituisce MF_E_TRANSFORM_TYPE_NOT_SET, passare al passaggio 3.
  3. (Facoltativo. Per ogni flusso di output, chiamare IMFTransform::GetOutputAvailableType per ottenere un elenco di tipi preferiti per tale flusso.
    • Se questo metodo restituisce MF_E_TRANSFORM_TYPE_NOT_SET, è necessario impostare prima i tipi di input; tornare al passaggio 1.
    • Se un flusso restituisce E_NOTIMPL, MFT non dispone di un elenco di tipi di output preferiti; andare al passaggio 4.
  4. Per ogni flusso di output, chiamare IMFTransform::SetOutputType per impostare il tipo di output. È possibile usare un tipo di supporto del passaggio 3 o un tipo che descrive il formato di output richiesto.
  5. Se i flussi di input non hanno un tipo di media, tornare al passaggio 1.

Ottenere i requisiti del buffer

Dopo che il client imposta i tipi di media, deve ottenere i requisiti del buffer per ogni flusso.

Elaborare i dati

Un MFT è progettato per essere una macchina a stati finiti affidabile. Non esegue alcuna chiamata al client.

  1. Chiamare IMFTransform::ProcessMessage con il messaggio di MFT_MESSAGE_NOTIFY_BEGIN_STREAMING. Questo messaggio richiede a MFT di allocare le risorse necessarie durante lo streaming.
  2. Chiamare IMFTransform::ProcessInput su almeno un flusso di input per recapitare un campione di input alla MFT.
  3. (Facoltativo. Chiamare IMFTransform::GetOutputStatus per verificare se MFT può generare un esempio di output. Se il metodo restituisce S_OK, controllare il parametro pdwFlags. Se pdwFlags contiene il flag di MFT_OUTPUT_STATUS_SAMPLE_READY, vai al passaggio 4. Se pdwFlags è zero, tornare al passaggio 2. Se il metodo restituisce E_NOTIMPL, andare al passaggio 4.
  4. Chiamare IMFTransform::P rocessOutput per ottenere i dati di output.
    • Se il metodo restituisce MF_E_TRANSFORM_NEED_MORE_INPUT, significa che MFT richiede più dati di input; tornare al passaggio 2.
    • Se il metodo restituisce MF_E_TRANSFORM_STREAM_CHANGE, significa che il numero di flussi di output è stato modificato o il formato di output è stato modificato. Il client potrebbe dover eseguire una query per individuare nuovi identificatori di flusso o impostare nuovi tipi multimediali. Per altre informazioni, vedere la documentazione per ProcessOutput.
  5. Se sono ancora presenti dati di input da elaborare, andare al passaggio 2. Se MFT ha utilizzato tutti i dati di input disponibili, procedere con il passaggio 6.
  6. Chiamare ProcessMessage con il messaggio di MFT_MESSAGE_NOTIFY_END_OF_STREAM.
  7. Chiamare ProcessMessage utilizzando il messaggio di MFT_MESSAGE_COMMAND_DRAIN.
  8. Chiamare ProcessOutput per ottenere l'output rimanente. Ripetere questo passaggio fino a quando il metodo non restituisce MF_E_TRANSFORM_NEED_MORE_INPUT. Questo valore restituito segnala che tutto l'output è stato scaricato dall'MFT. Non considerare questa condizione come una condizione di errore.

La sequenza descritta qui mantiene il minor numero possibile di dati in MFT. Dopo ogni chiamata a ProcessInput, il client tenta di ottenere l'output. Potrebbero essere necessari diversi esempi di input per produrre un esempio di output oppure un singolo esempio di input potrebbe generare diversi esempi di output. Il comportamento ottimale per il client consiste nell'estrarre i campioni di output da MFT fino a quando MFT non richiede più input.

Tuttavia, il MFT deve essere in grado di gestire un ordine diverso di chiamate al metodo dal client. Ad esempio, il client potrebbe semplicemente alternare tra le chiamate a ProcessInput e ProcessOutput. Il MFT deve limitare la quantità di input che riceve restituendo MF_E_NOTACCEPTING in ProcessInput qualora debba produrre un output.

L'ordine delle chiamate al metodo descritto di seguito non è l'unica sequenza valida di eventi. Ad esempio, i passaggi 3 e 4 presuppongono che il client inizi con i tipi di input e quindi tenti i tipi di output. Il client può anche invertire questo ordine e iniziare con i tipi di output. In entrambi i casi, se MFT richiede l'ordine opposto, deve restituire il codice di errore MF_E_TRANSFORM_TYPE_NOT_SET.

Il client può chiamare metodi informativi, ad esempio GetInputCurrentType e GetOutputStreamInfoin qualsiasi momento durante lo streaming. Il client può anche tentare di modificare i tipi di supporti in qualsiasi momento. MFT deve restituire un codice di errore se non è un'operazione valida. In breve, le MFP dovrebbero presupporre pochissime informazioni sull'ordine delle operazioni, diverse da quelle documentate nelle chiamate stesse.

Il diagramma seguente illustra un diagramma di flusso delle procedure descritte in questo argomento.

diagramma di flusso che conduce dall'ottenere identificatori di flusso mediante cicli che impostano tipi di input, ottengono input ed elaborano l'output

Estensioni al modello di base

Facoltativamente, un MFT può supportare alcune estensioni per il modello di streaming di base.

  • Flussi di lettura differita. Se il metodo IMFTransform::GetOutputStreamInfo restituisce il flag MFT_OUTPUT_STREAM_LAZY_READ per un flusso di output, il client non deve raccogliere dati da tale flusso di output. MFT continua ad accettare l'input e a un certo punto MFT eliminerà i dati di output da tale flusso. Se tutti i flussi di output hanno questo flag, l'MFT non fallirà mai nell'accettare l'input. Un esempio può essere una trasformazione di visualizzazione, in cui il client ottiene l'output solo quando ha cicli di CPU di riserva per disegnare la visualizzazione.
  • Flussi scartabili. Se il metodo GetOutputStreamInfo restituisce il flag MFT_OUTPUT_STREAM_DISCARDABLE per un flusso di output, il client può richiedere a MFT di eliminare l'output, ma MFT non eliminerà alcun output a meno che non sia richiesto. Quando MFT raggiunge il buffer di input massimo, il client deve raccogliere alcuni dati di output o richiedere a MFT di eliminare l'output.
  • Flussi facoltativi. Se il metodoGetOutputStreamInforestituisce il flag di MFT_OUTPUT_STREAM_OPTIONAL per un flusso di output o il metodo IMFTransform::GetInputStreamInfo restituisce il flag MFT_INPUT_STREAM_OPTIONAL per un flusso di input, tale flusso è facoltativo. Il cliente non deve impostare un tipo di media nel flusso. Se il client non imposta il tipo, il flusso viene deselezionato. Un flusso di output deselezionato non produce campioni e il client non fornisce un buffer per il flusso quando chiama ProcessOutput. Un flusso di input deselezionato non accetta dati di input. Un MFT può contrassegnare tutti i flussi di input e output come facoltativi. Tuttavia, è previsto che almeno un input e un output debbano essere selezionati per il funzionamento di MFT.
  • Elaborazione asincrona. Il modello di elaborazione asincrona è stato introdotto in Windows 7. Viene descritto nell'argomento MFT asincrone.

IMF2DBuffer

Se un MFT elabora dati video non compressi, deve usare l'interfaccia IMF2DBuffer per gestire i buffer di esempio. Per ottenere questa interfaccia, eseguire una query sull'interfaccia IMFMediaBuffer su qualsiasi buffer di input o output. Non utilizzare questa interfaccia quando è disponibile può comportare copie aggiuntive del buffer. Per usare correttamente questa interfaccia, la trasformazione non deve bloccare il buffer usando l'interfaccia IMFMediaBuffer quando è disponibile IMF2DBuffer.

Per altre informazioni sull'elaborazione dei dati video, vedere buffer video non compressi.

Svuotamento di un MFT

Il flushing di un MFT fa sì che l'MFT scarti tutti i suoi dati di input. Ciò può causare un'interruzione nel flusso di output. Un cliente in genere svuota un MFT prima di cercare un nuovo punto nel flusso di input o passare a un nuovo flusso di input, quando non si ha timore di perdere dati.

Per scaricare un MFT, chiamare IMFTransform::ProcessMessage con il messaggio di MFT_MESSAGE_COMMAND_FLUSH.

Svuotamento di un MFT

Svuotare un MFT fa sì che l'MFT produca tanto output quanto possibile da qualsiasi dato di input già inviato. Se gli MFT non sono in grado di produrre un esempio di output completo dall'input disponibile, i dati di input verranno scartati. Un client in genere svuota un MFT quando raggiunge la fine del flusso di origine o immediatamente prima di una modifica del formato nel flusso di origine. Per svuotare un MFT, eseguire le operazioni seguenti:

  1. Chiamare ProcessMessage con il messaggio di MFT_MESSAGE_COMMAND_DRAIN. Questo messaggio notifica all'MFT che dovrebbe fornire quanti più dati di output possibile dai dati di input già ricevuti.
  2. Chiamare ProcessOutput per ottenere i dati di output, fino a quando il metodo non restituisce MF_E_TRANSFORM_NEED_MORE_INPUT.

Durante il processo di svuotamento del MFT, non accetterà più input.

Attributi di esempio

Gli esempi di input possono avere attributi che devono essere copiati negli esempi di output corrispondenti.

Per un MFT con un input e un output, è possibile usare la regola generale seguente:

  • Se ogni esempio di input produce esattamente un esempio di output, è possibile consentire al client di copiare gli attributi. Lasciare la proprietà MFPKEY_EXATTRIBUTE_SUPPORTED non impostata.
  • Se non esiste una corrispondenza uno-a-uno tra campioni di input ed esempi di output, il MFT deve determinare gli attributi corretti per gli esempi di output. Impostare la proprietà MFPKEY_EXATTRIBUTE_SUPPORTED su VARIANT_TRUE.

Discontinuità

Una discontinuità è un'interruzione in un flusso audio o video. Le interruzioni possono essere causate da pacchetti eliminati in una connessione di rete, da dati di file danneggiati, da un flusso di origine a un altro o da un'ampia gamma di altre cause. Le discontinuità vengono segnalate impostando l'attributo MFSampleExtension_Discontinuity nel primo campione dopo la discontinuità. Non è possibile segnalare una discontinuità al centro di un campione. Pertanto, tutti i dati discontinui devono essere inviati in campioni separati.

Alcune trasformazioni, in particolare quelle che gestiscono dati non compressi, ad esempio gli effetti audio e video, devono ignorare le interruzioni quando elaborano i dati di input. Queste MFP sono in genere progettate per gestire i dati continui e devono trattare i dati ricevuti come continui, anche dopo una discontinuità.

Se un MFT ignora una discontinuità nei dati di input, deve comunque impostare il flag di discontinuità nell'esempio di output, se l'esempio di output ha lo stesso timestamp dell'esempio di input. Se l'esempio di output ha un timestamp diverso, l'MFT, tuttavia, non deve propagare la discontinuità. (Questo è il caso in alcuni ricampionatori audio, ad esempio. Una discontinuità nel punto sbagliato nel flusso è peggiore di nessuna discontinuità.

La maggior parte dei decodificatori non può ignorare le discontinuità, perché una discontinuità influisce sull'interpretazione del campione successivo. Qualsiasi tecnologia di codifica che usa la compressione tra frame, ad esempio MPEG-2, rientra in questa categoria. Alcuni schemi di codifica usano solo la compressione intra-frame, ad esempio DV e MJPEG. Questi decodificatori possono ignorare in modo sicuro le discontinuità.

Le trasformazioni che rispondono alle discontinuità devono in genere restituire la maggior parte dei dati prima della discontinuità possibile e rimuovere il resto. L'esempio di input con il flag di discontinuità deve essere elaborato come se fosse il primo esempio nel flusso. Questo comportamento corrisponde a quello specificato per il messaggio MFT_MESSAGE_COMMAND_DRAIN. Tuttavia, i dettagli esatti dipendono dal formato multimediale.

Se un decodificatore non esegue alcuna operazione per attenuare una discontinuità, deve copiare il flag di discontinuità nei dati di output. I demultiplexer e altri MFP che funzionano interamente con i dati compressi devono copiare eventuali discontinuità nei flussi di output. In caso contrario, i componenti downstream potrebbero non essere in grado di decodificare correttamente i dati compressi. In generale, è quasi sempre corretto passare discontinuità a valle, a meno che il MFT non contenga codice esplicito per smussare le discontinuità.

Modifiche al formato dinamico

I formati possono cambiare durante lo streaming. Ad esempio, le proporzioni possono cambiare nel mezzo di un flusso video.

Per informazioni dettagliate sulla gestione delle modifiche del flusso da parte di un MFT, vedere Gestione delle modifiche del flusso.

Eventi di streaming

Per inviare un evento a un MFT, chiamare IMFTransform::ProcessEvent. Se il metodo restituisce MF_S_TRANSFORM_DO_NOT_PROPAGATE_EVENT, la MFT restituirà l'evento al chiamante in una chiamata successiva a ProcessOutput. Se il metodo restituisce qualsiasi altro valore HRESULT, MFT non restituirà l'evento al client in ProcessOutput. In tal caso, il client è responsabile della propagazione dell'evento downstream al componente successivo nella pipeline, se applicabile. Per altre informazioni, vedere IMFTransform::ProcessOutput.

Media Foundation trasforma