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 nel MFT. Potrebbe trattarsi dell'applicazione o della pipeline di Media Foundation.

Leggere questo argomento se si è:

  • Scrittura di un'applicazione che effettua chiamate dirette a uno o più mft.
  • Scrittura di un MFT personalizzato e si vuole comprendere 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 asincrono , descritto nell'argomento MGT asincroni.

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 possono fornire altre opzioni, ad esempio una funzione di creazione specializzata.

Ottenere gli identificatori di flusso

Un MFT ha uno o più flussi. I flussi di input ricevono dati di input e i flussi di output generano dati di output. 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 i tipi di supporti

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 supporti preferiti per un flusso. Inoltre, le funzioni MFC 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, andare 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 supporto, tornare al passaggio 1.

Ottenere i requisiti del buffer

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

Elaborare dati

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

  1. Chiama IMFTransform::P rocessMessage con il messaggio di MFT_MESSAGE_NOTIFY_BEGIN_STREAMING . Questo messaggio richiede all'MFT di allocare le risorse necessarie durante lo streaming.
  2. Chiamare IMFTransform::P rocessInput su almeno un flusso di input per recapitare un campione di input al 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 MFT_OUTPUT_STATUS_SAMPLE_READY , andare 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 di supporti. Per altre informazioni, vedere la documentazione di 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 MFT_MESSAGE_NOTIFY_END_OF_STREAM .
  7. Chiamare ProcessMessage con il messaggio 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 svuotato dal MFT. Non considera 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. Alcuni esempi di input potrebbero essere necessari per produrre un esempio di output o un singolo esempio di input potrebbe generare diversi esempi di output. Il comportamento ottimale per il client consiste nel eseguire il pull degli esempi di output dal MFT fino a quando il MFT richiede più input.

Tuttavia, il MFT deve essere in grado di gestire un ordine diverso di chiamate di metodo dal client. Ad esempio, il client potrebbe semplicemente alternare le chiamate a ProcessInput e ProcessOutput. MFT deve limitare la quantità di input ottenuta restituendo MF_E_NOTACCEPTING da ProcessInput ogni volta che ha un output da produrre.

L'ordine delle chiamate al metodo descritto qui 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 GetOutputStreamInfo, in 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 mft dovrebbero assumere molto poco sull'ordine delle operazioni, diversamente da ciò che è documentato nelle chiamate stesse.

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

flow chart that leads from get stream identifiers through loops that set input types, get input, and process output

Estensioni al modello di base

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

  • Flussi di lettura lazy. Se il metodo IMFTransform::GetOutputStreamInfo restituisce il flag di 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 il MFT eliminerà i dati di output da tale flusso. Se tutti i flussi di output hanno questo flag, MFT non accetterà mai 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 scartati. Se il metodo GetOutputStreamInfo restituisce il flag di MFT_OUTPUT_STREAM_DISCARDABLE per un flusso di output, il client può richiedere all'MFT di eliminare l'output, ma il MFT non eliminerà alcun output a meno che non sia richiesto. Quando il MFT raggiunge il buffer di input massimo, il client deve raccogliere alcuni dati di output o richiedere al MFT di eliminare l'output.
  • Flussi facoltativi. Se il metodo GetOutputStreamInfo restituisce il flag di MFT_OUTPUT_STREAM_OPTIONAL per un flusso di output o il metodo IMFTransform::GetInputStreamInfo restituisce il flag di MFT_INPUT_STREAM_OPTIONAL per un flusso di input, tale flusso è facoltativo. Il client non deve impostare un tipo di supporto nel flusso. Se il client non imposta il tipo, il flusso viene deselezionato. Un flusso di output deselezionato non produce esempi e il client non fornisce un buffer per il flusso quando chiama ProcessOutput. Un flusso di input deselezionato non accetta i dati di input. Un MFT può contrassegnare tutti i flussi di input e di output come facoltativo. È tuttavia previsto che almeno un input e un output debbano essere selezionati per il funzionamento del MFT.
  • Elaborazione asincrona. Il modello di elaborazione asincrona è stato introdotto in Windows 7. Viene descritto nell'argomento MFT asincroni.

FMI2DBuffer

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

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

Scaricamento di un MFT

Lo scaricamento di un MFT causa l'eliminazione di tutti i dati di input da parte di MFT. Ciò può causare un'interruzione nel flusso di output. In genere un client scarica un MFT prima di cercare un nuovo punto nel flusso di input o passare a un nuovo flusso di input, quando il client non si preoccupa di perdere dati.

Per scaricare un MFT, chiamare FMTransform::P rocessMessage con il messaggio di MFT_MESSAGE_COMMAND_FLUSH .

Svuotamento di un MFT

Lo svuotamento di un MFT causa l'invio di MFT per la produzione dell'output da qualsiasi dato di input già inviato. Se MFT non riesce a produrre un esempio di output completo dall'input disponibile, i dati di input verranno rilasciati. 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 al MFT che deve recapitare il numero di dati di output possibile dai dati di input già inviati.
  2. Chiamare ProcessOutput per ottenere i dati di output, fino a quando il metodo non restituisce MF_E_TRANSFORM_NEED_MORE_INPUT.

Mentre il MFT è in fase di svuotamento, non accetterà più input.

Attributi di esempio

Gli esempi di input potrebbero 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 non impostata la proprietà MFPKEY_EXATTRIBUTE_SUPPORTED .
  • Se non esiste una corrispondenza uno-a-uno tra esempi di input e 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, dati di file danneggiati, un passaggio da un flusso di origine a un altro o da un'ampia gamma di altre cause. Le interruzioni vengono segnalate impostando l'attributo MFSampleExtension_Discontinuity nel primo esempio dopo la discontinuità. Non è possibile segnalare una discontinuità al centro di un campione. Pertanto, tutti i dati discontinui devono essere inviati in esempi separati.

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

Se un MFT ignora una discontinuità sui dati di input, deve comunque impostare il flag di interruzione 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, tuttavia, MFT non deve propagare la discontinuità. Questo è il caso in alcuni rimpler audio, ad esempio. Una discontinuità al posto sbagliato nel flusso è peggiore di nessuna discontinuità.

La maggior parte dei decodificatori non può ignorare le discontinuità, perché un'interruzione influisce sull'interpretazione del successivo esempio. 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 interruzioni devono in genere restituire la maggior parte dei dati prima della discontinuità possibile e eliminare il resto. L'esempio di input con il flag di interruzione deve essere elaborato come se fosse il primo esempio nel flusso. Questo comportamento corrisponde a quello specificato per il messaggio di MFT_MESSAGE_COMMAND_DRAIN . Tuttavia, i dettagli esatti dipenderanno dal formato multimediale.

Se un decodificatore non riduce la discontinuità, deve copiare il flag di interruzione nei dati di output. I demultiplexer e altri MFP che funzionano interamente con i dati compressi devono copiare tutte le interruzioni 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 le discontinuità downstream, a meno che il MFT non contenga codice esplicito per regolare 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 sul modo in cui vengono gestite le modifiche di flusso da un MFT, vedere Gestione delle modifiche al flusso.

Eventi di flusso

Per inviare un evento a un MFT, chiamare FMTransform::P rocessEvent. Se il metodo restituisce MF_S_TRANSFORM_DO_NOT_PROPAGATE_EVENT, 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 FMTransform::P rocessOutput.

Trasformazioni di Media Foundation